ForEach In List isn't targetting all - c#

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();
}
}

Related

Splitting String from Settings

I'm trying to read out the contents off a Setting inside my Application. Below is the code i'm having troubles with:
private bool checkGrid()
{
string playlists = Spotify_Extender.Properties.Settings.Default.Playlists;
MessageBox.Show(playlists);
string[] split1;
if (playlists.Contains(";"))
{
MessageBox.Show("Multiple Links");
split1 = playlists.Split(';');
}
else
{
MessageBox.Show("One Link");
split1 = new string[1];
split1[0] = playlists;
}
MessageBox.Show("Array Length: " + split1.Length);
int lines = 0;
for (int i = 0; i < split1.Length; i++)
{
MessageBox.Show("Check #" + i + " - " + split1[i] + " - Length: " + split1[i].Length);
if (split1[i].Length >= 22)
{
MessageBox.Show(i + " - " + split1[1]);
lines++;
}
}
int rows = this.playlistGrid.Rows.Count;
MessageBox.Show(lines + "");
if (rows == lines)
return true;
return false;
}
The code should be easy to understand and it should work as far as i am aware, but it doesn't. I entered this in my Setting:
If i run the program now, my first MessageBox prints out exactly what i entered, the second one prints out "One Link" and the third prints "Array Length: 1". Now we get to the part i'm having troubles with. The next Message is this:
So the length of the text is 22 as displayed in the MessageBox, but down below this statement isn't true:
if (split1[i].Length >= 22)
I'm really confused by this and it also does this when i check this:
if (split1[i] != "")
Any help is appreciated, because i don't know what to do, since my code should be fine. Thanks for your time!
You should have split[i] and not split[1]

C#, Split after 2 ;'s in same line

I'm generating a list of from/to coordinate points, together with the distance/time between those points.
For illustration: the header of the end product looks like this
writer.WriteLine("fromX" + ";" + "fromY" + ";" + "toX" + ";" + "toY" + ";" + "distance" + ";" + "time");
The process of calculating from point to point is as follows:
A -> A
A -> B
A -> C
..
B -> A
B -> B
B -> C
etc
The distance and time are per-calculated and are situated in a separate file. However, each line in this file consists of the distance/time between the same start point and every endpoint, thus for example:
0;0;11289;950;9732;899;9886;725;32893;2195;38010;2478;46188;3330;
The goal is to have the following notation in the end product:
point A;point A;0;0
point A;point B;11289;950
point A;point C;9732;899
etc.
As you can see, I would need to split the distance + time line at every 2nd value.
At the moment, I have the following code:
List<string> locationsList = new List<string>();
using (var reader = new StreamReader(File.OpenRead("locations.csv")))
{
while (reader.Peek() != -1)
locationsList.Add(reader.ReadLine());
}
List<string> distanceTime = new List<string>();
using (var reader = new StreamReader(File.OpenRead("distance.csv")))
{
while (reader.Peek() != -1)
distanceTime.Add(reader.ReadLine());
}
using (var writer = new System.IO.StreamWriter("Output.csv"))
{
writer.WriteLine("fromX" + ";" + "fromY" + ";" + "toX" + ";" + "toY" + "distance" + ";" + "time")
foreach (var fromLine in locationsList)
{
splitFrom = fromLine.Split(';');
fromX = splitFrom[0].Trim();
fromY = splitFrom[1].Trim();
foreach (var toLine in locationsList)
{
splitTo = toLine.Split(';');
toX = splitTo[0].Trim();
toY = splitTo[1].Trim();
writer.WriteLine(fromX + ";" + fromY + ";" + toX + ";" + toY);
}
}
MessageBox.Show("Done");
}
This would have to be expanded with probably a foreach loop that reads a line from the distanceTime-list, splits it, takes every first 2 values and writes them together with the start -and end point.
Problem is that I have no idea how to split after every 2nd value.
Do you have any suggestions?
You don't really need to split on every second ';', you just need a slightly different for loop:
using System;
class Program {
static void Main(string[] args) {
string line = "0;0;11289;950;9732;899;9886;725;32893;2195;38010;2478;46188;3330;";
string[] values = line.Split(';');
char pointName = 'A';
for (int i = 0; i < values.Length - 1; i += 2) {
string endProductLine = string.Format("point A;point {0};{1};{2}", pointName, values[i], values[i + 1]);
Console.WriteLine(endProductLine);
pointName++;
}
}
}
https://msdn.microsoft.com/en-us/library/0w4e0fzs.aspx
Use the % operator:
string coords = "0;0;11289;950;9732;899;9886;725;32893;2195;38010;2478;46188;3330;";
string[] values = coords.Split(';');
for(int val=0; val<values.Length; val++)
{
int coord;
if(val % 2 == 0)
{
//this will give you access to every second value
int.TryParse(values[val], out coord);
Console.WriteLine(coord.ToString());
}
}

Confusing indexing error while going line by line through some text

I'm reading in some text, line by line, and I'd like to tokenize the words and create 1-grams and 2-grams, but I think there's a problem with my indexing because I either get an index error or it'll say that the item I'm trying to modify in my dictionary doesn't exist, which is totally weird, since I wrote the code to first make the dictionary item and if it already exists, to increment a counter.
Basically, my dictionaries are of the form (n-gram string, frequency int)
System.IO.StreamReader lines = new System.IO.StreamReader("myfile");
while (true)
{
string line = lines.ReadLine().ToLower();
if (line == null) break;
if (line.Trim().Length == 0) continue;
string[] tokens = Regex.Split(line, "[^\\w']+");
for (int i = 0; i < tokens.Count()-1; i++)
{
try
{
one_gram.Add(tokens[i], 1);
two_gram.Add(tokens[i] + " " + tokens[i + 1], 1);
}
catch
{
one_gram[tokens[i]]++;
two_gram[tokens[i] + " "+tokens[i + 1]]++;
}
}
}
Can anyone look at my code and tell me where I went wrong? The problem seems to occur at the end of the for loop at the first line, but if I do
for(int i=0;i<tokens.Count()-3;i++)
then the error happens in the second line... but I'm not sure exactly what's causing it.
EDIT: As per suggestions, I tried using the ContainsKey method, but I still get an error near the end of the first line saying that I'm adding a Key that already exists, even though the if statements are supposed to catch that?!
for (int i = 0; i < tokens.Count()-1; i++)
{
if (one_gram.ContainsKey(tokens[i]))
{
one_gram[tokens[i]]++;
}
if (two_gram.ContainsKey(tokens[i] + " " + tokens[i + 1]))
{
two_gram[tokens[i] + " " + tokens[i + 1]]++;
}
one_gram.Add(tokens[i], 1);
two_gram.Add(tokens[i] + " " + tokens[i + 1], 1);
}
You need to use an else (or break):
for (int i = 0; i < tokens.Count() - 1; i++)
{
// Save yourself typing errors by creating variables to hold
// the key values and then you can just use the variable name
var oneGramKey = tokens[i];
var twoGramKey = string.Format("{0} {1}", tokens[i], tokens[i + 1]);
if (one_gram.ContainsKey(oneGramKey))
{
one_gram[oneGramKey]++;
}
else
{
one_gram.Add(oneGramKey, 1);
}
if (two_gram.ContainsKey(twoGramKey))
{
two_gram[twoGramKey]++;
}
else
{
two_gram.Add(twoGramKey, 1);
}
}

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