For Loop not writing all instances in array - c#

i am working on a program that uses a list of employees:
List<Employee> emp = new List<Employee>();
emp.Add(new Employee("Bran", 2500));
emp.Add(new Employee("Mike", 1500));
emp.Add(new Employee("Isaac", 1000));
emp.Add(new Employee("Patrick", 100));
emp.Add(new Employee("Spongebob", 2000));
emp.Add(new Employee("Spongegar", 1200));
I am using linq to make a query and i want to do a sequential search so i put:
Console.WriteLine("\nResults of sequential search ");
Employee em = null; //flag
string name = "Spo";
int i;
var match = from e in emp
where e.Name.StartsWith(name)
select e;
em = match.FirstOrDefault();
i = emp.IndexOf(em);
MoreEmployee();
if (match.Any())
{
for (int x =0; x < emp.Count; x++)
{
Console.WriteLine((x +1) + ". " + em.Name + " " + em.Salary.ToString("C") + " " + em.AnnualSal.ToString("C"));
}
}
else
{
Console.WriteLine("Employee Not found");
}
this output is giving me Songebob 6 times and not Songebob and Spongegar, what im i doing wrong? how do i get it to iterate through properly?

At em = match.FirstOrDefault(); the em is getting Songebob. And your for loop later on is iterating 6 times, printing it. It should be
if (match.Any())
{
var x = 1;
foreach (var empl in match)
{
Console.WriteLine(x++ + ". " + empl.Name + " "
+ empl.Salary.ToString("C") + " " + empl.AnnualSal.ToString("C"));
}
}
else
{
Console.WriteLine("Employee Not found");
}

try this:
List<Employee> emp = new List<Employee>();
emp.Add(new Employee("Bran", 2500));
emp.Add(new Employee("Mike", 1500));
emp.Add(new Employee("Isaac", 1000));
emp.Add(new Employee("Patrick", 100));
emp.Add(new Employee("Spongebob", 2000));
emp.Add(new Employee("Spongegar", 1200));
string name = "Spo";
var match= emp.Where(y => y.Name.StartsWith(name)).ToList();
if (match.Any())
{
for (int x = 0; x < match.Count; x++)
{
Console.WriteLine((x +1) + ". " + match[x].Name + " " +
match[x].Salary.ToString("C") + " " +match[x].AnnualSal.ToString("C"));
}
}
else
{
Console.WriteLine("Employee Not found");
}
hope this helps...

As #DotNet Developer said, your loop is iterating 6 times "on the same value" -- Spongebob.
The problem is that you are referencing the wrong count in your For loop. You have found the index of the correct employee "Spongebob" from your original emp list, but you don't reference that value again. They are also the first in the result set, but you are referencing that same employee over and over again a total of 6 times (the number of total employees in emp) but your result set, em only contains 2 employees.
Instead of using a For loop, either use the suggestion by #DotNet Developer and use a Foreach loop on the result set, em and refer to the count of this result set in your For loop -- x < em.Count; then access the list memebers with their list position em[x].Name ...
OR
Try this instead of your code to find the match and reference the result set em in your Console.Writeline statement:
Console.WriteLine("\nResults of sequential search ");
string name = "Spo";
List<Employee> em = emp.Where(e => e.Name.StartsWith(name)).ToList();
for (int x = 0; x < em.Count; x++)
{
Console.WriteLine((x + 1) + ". " + em[x].Name + " " + em[x].Salary.ToString("C") + " " + em[x].AnnualSal.ToString("C"));
}
/* or simplify accessing the list elements by using a Foreach loop */
Console.WriteLine("or, using a Foreach loop:");
int i = 0;
foreach (var employee in em)
{
Console.WriteLine((++i) + ". " + employee.Name + " " + employee.Salary.ToString("C") + " " + employee.AnnualSal.ToString("C"));
}

Related

How can i use ' ++ i ' inside this situation?

I want to draw a random name for an event where users can win items specified by their ID (1,2,3 etc.). The random name part is ok by now but how can i display the result like:
The ID : 1 winner is: 'the random name'
The ID : 2 winner is: 'the random name'
etc...
till ID : 27
static void Main(string[] args)
{
string[] Names = { "Erik", "Levente", "Noel", "Áron", "Krisztián", "Kristóf", "Bence", "Roland", "Máté", "László", "Bálint" ,
"Regina", "Brigitta", "Gréta", "Hédi", "Hanna", "Boglárka", "Jázmin", "Réka", "Alexandra", "Rebeka", "Lili", "Luca", "Zsófi"};
List<string> alreadyUsed = new List<string>();
Random r = new Random();
while (alreadyUsed.Count < Names.Length)
{
int index = r.Next(0, Names.Length);
if (!alreadyUsed.Contains(Names[index]))
{
alreadyUsed.Add(Names[index]);
Console.WriteLine("The ID : 1 winner is: " + Names[index]);
}
}
Console.ReadKey(true);
}
Here is a refactored appraoch without that bad performing alreadyUsed. First I randomize the array, second I iterate and display each item with a incrementing index / id.
string[] Names = { "Erik", "Levente", "Noel", "Áron", "Krisztián", "Kristóf", "Bence", "Roland", "Máté", "László", "Bálint" , "Regina", "Brigitta", "Gréta", "Hédi", "Hanna", "Boglárka", "Jázmin", "Réka", "Alexandra", "Rebeka", "Lili", "Luca", "Zsófi"};
Random r = new Random();
Names = Names.OrderBy(_ => r.Next()).ToArray();
for(int i=0;i< Names.Length;i++)
{
Console.WriteLine("The ID : " + (i+1) + " winner is: " + Names[i]);
}
while (alreadyUsed.Count < Names.Length)
{
int index = r.Next(0, Names.Length);
if (!alreadyUsed.Contains(Names[index]))
{
alreadyUsed.Add(Names[index]);
Console.WriteLine("The ID : " + alreadyUsed.Count + " winner is: " + Names[index]);
}
}
You do not need ++i, you already have the position contained in alreadyUsed.Count that will increment itself as you use alreadyUsed.Add(...).
Try it online

ForEach In List isn't targetting all

so I currently have a program that adds an item to a list in a format such as
username,Index it then adds one to the index in this code below however. It is only adding one to the item that has been added most recently.
Console.WriteLine("There are currently: " + AntiSpam.Count);
int Index = 0;
foreach (string s in AntiSpam)
{
Console.WriteLine("Found User: " + s.Split(',')[0]);
AntiSpam[Index] = s.Split(',')[0] + "," + (int.Parse(s.Split(',')[1]) + 1).ToString();
Index++;
}
Basically this returns the data There are currently: 10
Found User: someone. It then goes again for another loop of this code and shows the same result again.
EDIT
I have managed to make my code work by using this code
for (var i = 0; i < AntiSpam.Count; i++)
{
AntiSpam[i] = AntiSpam[i].Split(',')[0] + "," + (int.Parse(AntiSpam[i].Split(',')[1]) + 1).ToString();
Console.WriteLine("Text is {0}", AntiSpam[i]);
}
However if possible I would like to know why this works and the first doesn't
If you're going to be indexing a list, just do for rather than foreach. This avoids the need (and possible confusion) of using a separate variable to keep track of the AntiSpam.IndexOf(s) which is basically what you were trying to do with Index:
Console.WriteLine("There are currently: " + AntiSpam.Count);
int index;
string s;
for(int i=0; i < AntiSpam.Count, i++)
{
string[] parts = AntiSpam[i].Split(',');
username = parts[0];
Console.WriteLine("Found User: " + username);
if (parts.Length > 1)
{
index = int.Parse(parts[1])
AntiSpam[i] = username + "," + (index + 1).ToString();
}
}

How do I initialize an array to avoid a NullReferenceException error in this case [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
I am getting this error and I have absolutely no idea how to get rid of it. I allocated the array but cant seem to get it initialized correctly. I allocated the array on line 13 NullReference error. I read about it but in this case I have no idea what I'm doing wrong.
I have the following code.
namespace A4
{
public partial class frmAddStudent : Form
{
public frmAddStudent()
{
InitializeComponent();
}
// Declare variables to be used by both event handlers
int CountStudents = 0;
double Average = 0;
Student[] ClassList = new Student[50];
private void btnAdd_Click(object sender, EventArgs e)
{
// Create new student and assign name etc provided by user
Student _Student = new Student();
_Student.Name = txtName.Text;
_Student.Surname = txtSurname.Text;
_Student.Age = Convert.ToInt32(txtAge.Text);
_Student.ITMark = Convert.ToInt32(txtIT.Text);
_Student.MathMark = Convert.ToInt32(txtEng.Text);
_Student.EngMark = Convert.ToInt32(txtMath.Text);
// Use the hasPassed method to display an appropriate message after the
// student has been added
MessageBox.Show("Student added.");
// Increase counter and display how many students added so far
CountStudents++;
Average = Convert.ToInt32(txtIT.Text) + Convert.ToInt32(txtEng.Text) + Convert.ToInt32(txtMath.Text);
_Student.AverageMark = Average / 3;
//Display Student's properties
richTextBox1.Text += ("Student: " + Convert.ToString(CountStudents) +
"\nName: " + _Student.Name +
"\nSurname: " + _Student.Surname +
"\nAge: " + _Student.Age +
"\nStudent Average: " + Convert.ToString(_Student.AverageMark) + "\n" + "\n");
//Add the newly added student to the ClassList array
ClassList[CountStudents - 1] = _Student;
//Clear the list
txtSurname.Clear();
txtName.Clear();
txtAge.Clear();
txtIT.Value = 0;
txtEng.Value = 0;
txtMath.Value = 0;
txtName.Focus();
}
private void displayAll_Click(object sender, EventArgs e)
{
richTextBox1.Clear();
for (int j = 0; j < ClassList.Count(); j++)
{
richTextBox1.Text += ("Student: " + Convert.ToString(j) +
"\nName: " + ClassList[j].Name +
"\nSurname: " + ClassList[j].Surname +
"\nAge: " + ClassList[j].Age +
"\nStudent Average: " + Convert.ToString(ClassList[j].AverageMark) +
"\n" + "\n");
}
//MessageBox.Show("Display all students.");
}
}
}
I suspect your null reference is being thrown in the displayAll_Click method. In that method you iterate over all the elements in the array (i.e. all 50), whether they have a student or not. This is because the Count() returns the length of the array, not the count of array elements that have a Student in them.
You should use either your student count variable CountStudents, in the for loop, or better yet, use List<Student>, which is ideal for your use, and less prone to these problems than an array.
What is "Count()" in the loop:
ClassList.Count();
Did you mean ClassList.Length;?
If you are populating the array dynamically, it's better to use List<Student> ClassList you get less problems with it.

Data lost while adding string to listbox

I am cycling through the contents of a two-dimensional array containing the result of a Punnett Square calculation for gene crosses. I need to summarize the result so that the user can readily see the unique instances. I can accomplish this by putting the result into a text box, but when I try and use a ListBox to display the data, part of the information is getting lost, namely a translation of the AaBBCc type data to something that directly relates to the traits that the user initially selected.
This is the main block of code for the operation:
foreach (string strCombination in arrUniqueCombinations)
{
int intUniqueCount = 0;
decimal decPercentage;
foreach (string strCrossResult in arrPunnettSQ)
{
if (strCrossResult == strCombination)
{
intUniqueCount++;
}
}
decPercentage = Convert.ToDecimal((intUniqueCount*100)) / Convert.ToDecimal(intPossibleCombinations);
txtReport.AppendText(strCombination + " appears " + intUniqueCount.ToString() + " times or " + decPercentage.ToString() + "%."+ Environment.NewLine);
lstCrossResult.Items.Add(DecodeGenome(strCombination) + " appears " + intUniqueCount.ToString() + " times or " + decPercentage.ToString() + "%.");
}
For appending the data to the textbox I use this code and it works perfectly:
txtReport.AppendText(DecodeGenome(strCombination) + " appears " + intUniqueCount.ToString() + " times or " + decPercentage.ToString() + "%."+ Environment.NewLine);
Giving the result:
Trait 1 Het.,Trait 3 appears 16 times or 25%.
For adding the result to a list box, this works:
lstCrossResult.Items.Add(strCombination + " appears " + intUniqueCount.ToString() + " times or " + decPercentage.ToString() + "%.");
Giving the result:
AaBBCc appears 16 times or 25%.
But the contents of strCombination is AaBBCc and I need it translated to "Trait 1 Het.,Trait 3", which I accomplish with this bit of code:
private string DecodeGenome(string strGenome)
{
string strTranslation = "";
int intLength = strGenome.Length;
int intCounter = intLength / 2;
string[] arrPairs = new string[intLength / 2];
//Break out trait pairs and load into array
for (int i = 1; i <= intLength; i++)
{
arrPairs[i / 2] = strGenome.Substring((i-1),2);
i++;
}
foreach (string strPair in arrPairs)
{
char chFirstLetter = strPair[0];
char chSecondLetter = strPair[1];
intCounter = intCounter - 1;
if (Char.IsUpper(chFirstLetter))
{
if (!Char.IsUpper(chSecondLetter))
{
if (intCounter > 0)
{
txtReport.AppendText(GetDescription(strPair.Substring(0, 1)) + " Het.,");
}
else
{
txtReport.AppendText(GetDescription(strPair.Substring(0, 1)));
}
}
}
else
{
if (!Char.IsUpper(chSecondLetter))
{
if (intCounter > 0)
{
txtReport.AppendText(GetDescription(strPair.Substring(0, 1)) + ",");
}
else
{
txtReport.AppendText(GetDescription(strPair.Substring(0, 1)));
}
}
}
}
return strTranslation;
}
That has no problem displaying in a text box, but when I try and put it as an item into a list box it turns it into null. Instead of:
"Trait 1 Het.,Trait 3 appears 16 times or 25%."
I get:
" appears 16 times or 25%."
I have tried adding the results to an ArrayList, then populating the listbox after everything is processed, but the result is the same.
Any clues as to why the list box is not accepting the translated AaBBCc information would be greatly appreciated.
strTranslation is never set. Everything is pushed to txtReport.AppendText

proper way assign numer to elements in a List Collection

I am looping through a list of elements, and would like to assign a number to where each element resides in the Collection for deletion puposes. My code below, just gives me the count, is there another option to achieve this. Ex.
0 cat
1 dog
2 fish
ect..
foreach (string x in localList)
{
{
Console.WriteLine( localList.Count + " " + x);
}
}
be old school and go back to a standard for loop:
for(int i = 0; i < localList.Count; ++i)
{
string x = localList[i];
// i is the index of x
Console.WriteLine(i + " " + x);
}
If you really want to get fancy, you can use LINQ
foreach (var item in localList.Select((s, i) => new { Animal = s, Index = i }))
{
Console.WriteLine(item.Index + " " + item.Animal);
}
you have to use a for loop or use a separate index:
for(int i = 0; i < localList.Count;i++)
{
Console.WriteLine( i + " " + localList[i]);
}
Depending on the collection type you are using you can use something like
foreach (string x in locallist)
{
Console.WriteLine(locallist.IndexOf(x) + " " + x);
}
regds, perry

Categories

Resources