C# For Loop How to Display Only Matching Values - c#

My assignment is to create a string list that has at least two matching values and then to prompt the user to input one of those values and then I am to display the index or indices of that value entered.
I seem to have figured out how to get the desired indices to show, but I also need to have a statement in the event the value entered is not in the list and when I do an else, it messes things up. Looking for some help on this!
So this does what I want but without the else statement:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<string> mprovinces = new List<string> { "Nova Scotia", "New Brunswick", "Prince Edward Island", "Nova Scotia" };
Console.WriteLine("Enter one of the following maritime provinces: \nNova Scotia, \nNew Brunswick, \nPrince Edward Island\n");
string input2 = Console.ReadLine();
for (int i = 0; i < mprovinces.Count; i++)
{
bool match = mprovinces[i] == input2;
if (match)
{
Console.WriteLine(i);
}
}
}
}
But when I add an else statement and I enter a value that is in the list it provides more data than I want:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<string> mprovinces = new List<string> { "Nova Scotia", "New Brunswick", "Prince Edward Island", "Nova Scotia" };
Console.WriteLine("Enter one of the following maritime provinces: \nNova Scotia, \nNew Brunswick, \nPrince Edward Island\n");
string input2 = Console.ReadLine();
for (int i = 0; i < mprovinces.Count; i++)
{
bool match = mprovinces[i] == input2;
if (match)
{
Console.WriteLine(i);
}
else
{
Console.WriteLine("Sorry, this is not in the list");
}
}
}
}

Since the "Sorry" message is inside of the for loop you will show it for EVERY index that does not exactly match your input2. You need to pull the match value out of the for loop and check it once.
var matchIndex = -1; // can never get a -1 so it's a good default to check for later
for (int i = 0; i < mprovinces.Count; i++)
{
if (mprovinces[i] == input2)
{
matchIndex = i;
break; // break out of loop
}
}
if (matchIndex >= 0) // again a valid index will never be below 0
{
Console.WriteLine("Index: " + matchIndex);
}
else
{
Console.WriteLine("Sorry, this is not in the list");
}
I'm not sure exactly what you want to show. If you only want to show the FIRST index that matches then the above code will work. If you want to show EVERY index that matches then this would work.
EDIT: I have changed this function to not use a string to keep track of the list. It just shows the matching indexes as they appear.
bool matchExists = false;
for (int i = 0; i < mprovinces.Count; i++)
{
if (mprovinces[i] == input2)
{
matchExists = true;
Console.WriteLine(i);
}
}
if (matchExists == false)
{
Console.WriteLine("Sorry, this is not in the list");
}

Related

my Distinct function is not working and i can't see why c#

The Distinct function is not working when it should. This is the input I am using:
one one two
Distinct
End
this is my whole code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Array.Processing
{
class Program
{
static void Main(string[] args)
{
string input = Console.ReadLine();
List<string> texts = input.Split(" ").ToList();
string text = Console.ReadLine();
int a = 0;
while (text != "END")
{
text = Console.ReadLine();
List<string> infos = text.Split(" ").ToList();
if (text == "Distinct")
{
texts = texts.Distinct().ToList();
}
if (text == "Reverse")
{
texts.Reverse();
}
if (infos[0] == "Replace")
{
if (texts.Count > int.Parse(infos[1]) && int.Parse(infos[1]) >= 0)
{
texts.RemoveAt(int.Parse(infos[1]));
texts.Insert(int.Parse(infos[1]), infos[2]);
}
else
{
a++;
}
}
}
for(int n = 0; n < a; n++)
{
Console.WriteLine("Invalid input!");
}
foreach (string info in texts)
{
Console.Write(info + " ");
}
}
}
}
and this is the output I am receiving:
one one two
I can't figure out why both "one" remains. Been looking at the code for over an hour so far and still nothing...
First you have
string input = Console.ReadLine(); // one one two
Next you have
string text = Console.ReadLine(); // Distinct
Next, first time inside the while you have
text = Console.ReadLine(); // End
At this point you check if (text == "Distinct") but by now its been overwritten to "End" so you never end up calling Distinct() on the list.

for loop skip list elements

i have a problem with the code i showed below.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace problem2
{
class Program
{
static void Main(string[] args)
{
int[] nums = Console.ReadLine().Split().Select(int.Parse).ToArray();
List<int> lst = nums.OfType<int>().ToList();
while (true)
{
string des = Console.ReadLine();
var output = Regex.Replace(des.Split(" ")[0], #"[^0-9a-zA-Z\ ]+", "");
if (output == "Add")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
lst.Add(value);
}
else if(output == "Remove")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
lst.Remove(value);
}else if(output == "Replace")
{
String result1 = System.Text.RegularExpressions.Regex.Match(des, #"\d+").Value;
var lastno = des.Split().Last();
List<int> lst2 = lst;
for (int i = 0; i < lst2.Count; i++)
{
if(lst[i] == int.Parse(result1))
{
lst[i] = int.Parse(lastno);
break;
}
}
lst = lst2;
}
else if(output == "Collapse")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
}
else
{
continue;
}
}
}else if (output == "Mort")
{
PrintValues(lst);
break;
}
}
}
public static void PrintValues(IEnumerable myList)
{
foreach (Object obj in myList)
Console.Write("{0} ", obj);
Console.WriteLine();
}
}
}
more precisely with this part of the code:
else if(output == "Collapse")
{
string val = Regex.Replace(des, "[^0-9]", "");
int value = int.Parse(val);
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
}
else
{
continue;
}
}
I tried with all sorts of options but the loop misses elements. as an example
entrance:
1 2 -1 0 -3 9 8 7 2
Collapse 8
Mort
output:
9 8
but the program gives me this output:
2 0 9 8 2
I tried to see what the problem is through the debugger and there I found that the loop misses elements
It should be,
for(int i = 0; i < lst.Count; i+=1)
{
int element = (int)lst[i];
if (element < value)
{
lst.RemoveAt(i);
i--;
}
else
{
continue;
}
}
As #David784 mentioned at the comments. When you remove element the from the itterating collection. You miss 1 element everytime after you delete the i item.
To elaborate on #Berkay's comment: You're changing a list as you're looping through it. If i is 2 and you remove that element, then the element that used to be at index 3 now becomes 2, and so forth. His method of decrementing i will work. Another way would be to use a linq .Where statement instead:
var newList = lst.Where(e=> e>=value).ToList();
You are modifying the collection you are iterating through. This moves elements to other indexes and invalidates the i you determine for following elements in the for header. Better loop backwards
for (int i = lst.Count - 1; i >= 0; i--) {
// Now you can safely remove (or add) elements without affecting
// the index of non yet processed elements.
}
You are still modifying the index of elements ahead, but you are moving backwards, now.
In Visual Studio, you can use the forr code snippet to create a reverse for-loop. Type
forr <tab> <tab>.
(and of course there is the for code snippet for a normal for loop. It will increment the index with i++ instead of i += 1.)
Also, if the list is very long and you are removing many elements, it is worth to think about performance. This approach could move around a great number of elements. Copying the elements you want to keep to a new list (initialized with an appropriate initial capacity), will be more performing in this case.

A problem that I tried to solve with the help of strings and repetitive instructions, but on the console the result is not what I expected

using System;
class Program
{
static void Main(string[] args)
{
string candidateName = Console.ReadLine();
string input = Console.ReadLine();
int numberOfAdmittedPersons = Convert.ToInt32(input);
string result = string.Empty;
for (int i = 1; i <= numberOfAdmittedPersons; i++)
{
string listOfAllAdmittedPersons = Console.ReadLine();
{
if (i != numberOfAdmittedPersons)
{
result += listOfAllAdmittedPersons;
}
}
}
if (result.Contains(candidateName))
{
Console.WriteLine("true");
}
else
{
Console.WriteLine("false");
}
}
}
The application receives on the first line the name of a candidate C (inputted by the user). The next line contains the number of persons admitted (also inputted by the user).Then the list of all admitted persons follows, one person per line (also inputted by the user).
I have to make an application which displays "True" if candidate C was admitted (C is found in the list) or "False" if the candidate was rejected (C is not on the list)
for example : if I input :
John
3
George
Maria
John
The console will display : true
But the result I get is : false.
What can I do to correct my code?
Your code has a couple of issues. What is causing your bug is this line:
if (i != numberOfAdmittedPersons)
It means the last name is not being added to your string.
However there is another problem. Given the following input:
MAX
2
AMA
XAVIER
The result would be true as the string AMAXAVIER contains the string MAX. The answer is to use a collection, for example:
string[] result = new string[numberOfAdmittedPersons];
for (int i = 0; i < numberOfAdmittedPersons; i++)
{
result[i] = Console.ReadLine();
}
if (result.Contains(candidateName))
{
...
Another way is to define a list to store the names.
List<string> result = new List<string>();
for (int i = 0; i < numberOfAdmittedPersons; i++)
{
// add items
result.Add(Console.ReadLine());
}
if (result.Contains(candidateName))
{
// ...
}

A simple iteration with if else

Iterating through an array of strings i want it to write a specific line if one of the elements coresponds to the condition. The problem is with the else condition. It is written as many times as the length of the array and i only need it written once
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
}
else
{
Console.WriteLine("He was not here");
}
}
}
static void Main(string[] args)
{
{
FindSandy("Bob","Bella", "Sandy", "Nemo", "Dory");
}
}
What about if you just return if you found it?
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
// Found, you can return from method.
return;
}
}
// Not found, write the 'not found' message.
Console.WriteLine("He was not here");
}
The simplest way to change your code to handle this is to create a variable that tracks the index where Sandy is found, initialize it to an invalid value (like -1), and then set it to the actual value in your if block (and we can also add a break; statement to exit the loop as soon as we find him).
Then, we output a string based on the value of the position variable:
public static void FindSandy(params string[] ocean)
{
int position = -1;
for (int i = 0; i < ocean?.Length; i++)
{
if (ocean[i] == "Sandy")
{
position = i;
break;
}
}
if (position > -1)
{
Console.WriteLine("We found Sandy on position {0}", position);
}
else
{
Console.WriteLine("He was not here");
}
}
The code can be simplified a little with the System.Linq extension methods Select (to select the name and then index) and FirstOrDefault which returns the first item that meets a condidion, or the default for the type (which is null):
public static void FindSandy(params string[] ocean)
{
var position = ocean?.Select((name, index) => new {name, index})
.FirstOrDefault(item => item.name == "Sandy");
Console.WriteLine(position == null
? "He was not here"
: $"We found Sandy on position {position.index}");
}
You can use the keyword break to exit the for loop :
public static void FindSandy(params string[] ocean)
{
for (int i = 0; i < ocean.Length; i++)
{
if (ocean[i] == "Sandy")
{
Console.WriteLine("We found Sandy on position {0}", i);
break;
}
else if (i == ocean.Length - 1)
{
Console.WriteLine("He was not here");
break;
}
}
}
To solve your issue, you could add a new boolean variable (e.g. weFoundSandy): if you find an occurrence, set this variable to true, use the break statement (to reduce the iterations of the for) and, at the end, use this boolean variable to determine which message to display.
public static void FindSandy(params string[] ocean) {
bool weFoundSandy = false;
for (int i = 0; i < ocean.Length; i++) {
if (ocean[i] == "Sandy") {
Console.WriteLine("We found Sandy on position {0}", i);
weFoundSandy = true;
break;
}
}
if (!weFoundSandy) {
Console.WriteLine("Sandy was not here");
}
}
or, you could simply use the C# Array.IndexOf method, e.g.:
public static void FindSandy(params string[] ocean) {
int indexOfSandy = Array.IndexOf(ocean, "Sandy");
if (indexOfSandy >= 0) {
Console.WriteLine("We found Sandy on position {0}", indexOfSandy);
} else {
Console.WriteLine("Sandy was not here");
}
}

Getting User Input and Adding it to an array at C#

I am trying to get input from user 5 times and add those values to marks array;
Then, it will calculate the average and print positive or negative accordingly. However, I can not take input from the user it just prints "Enter 5 elements". After getting input from user how can I add them to marks array? Any tips would be helpful.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
double average =0;
int [] marks = new int[] { };
for (int a = 0; a < 5; a++){
Console.WriteLine("Enter 5 elements:");
string line = Console.ReadLine();
Console.WriteLine(line);
}
for (int i = 0; i < marks.Length; i++){
average = marks.Average();
}
if(average>0){
Console.WriteLine("Positive");
}else{
Console.WriteLine("Negative");
}
}
}
I would use a while loop combined with int.TryParse to check if the user input is a number. Also it doesn't make any sense to put average = marks.Average(); inside a for loop, because LINQ Average calculates the average of a collection (in your case the marks array).
static void Main()
{
int[] marks = new int[5];
int a = 0;
Console.WriteLine("Enter 5 elements:");
while (a < 5)
{
if (int.TryParse(Console.ReadLine(), out marks[a]))
a++;
else
Console.WriteLine("You didn't enter a number! Please enter again!");
}
double average = marks.Average();
if (average > 0)
Console.WriteLine("Positive");
else
Console.WriteLine("Negative");
}
DEMO HERE
Edited my answer to illustrate solving your problem without a for loop.
class Program
{
const int numberOfMarks = 5;
static void Main()
{
List<int> marks = new List<int>();
Enumerable.Range(1, numberOfMarks)
.ForEach((i) => {
Console.Write($"Enter element {i}:");
marks.Add(int.TryParse(Console.ReadLine(), out var valueRead) ? valueRead : 0);
Console.WriteLine($" {valueRead}");
});
Console.WriteLine(marks.Average() >= 0 ? "Positive" : "Negative");
}
}
This will help you, just copy and paste it.
There are some explanation with comments.
class Program
{
static void Main()
{
const int numberOfMarks = 5;
int[] marks = new int[numberOfMarks];
Console.WriteLine("Enter 5 elements:");
for (int a = 0; a < numberOfMarks; a++)
{
// If entered character not a number, give a chance to try again till number not entered
while(!int.TryParse(Console.ReadLine(), out marks[a]))
{
Console.WriteLine("Entered not a character");
}
Console.WriteLine("You entered : " + marks[a]);
}
// Have to call Average only once.
var avg = marks.Average();
Console.WriteLine(avg > 0 ? "Positive average" : "Negative average");
Console.ReadLine();
}
}
Follow Stackoverflow Answer
since integer array is being used, and as input from the console is a string value, you need to convert it using Parse() Method. For e.g.
string words = "83";
int number = int.Parse(words);
Edit: using string variable in parsing.

Categories