Reputation: 11
I am trying to read a file into a global array, loop through the array and identify each string to it's corresponding amount, and then find the sums in their own groups. and divide those groups each by their own unique number.
The text file that I am reading in:
Name,50
Name,40
DifferentName,50
AnotherName,10
Name,60
What would be the easiest way to split the lines at the commas, and make the numbers correspond to their specific names, not knowing which order they will be in?
Here is the code I am using so far..although right now it is just the open file dialog, I am putting this here as a constructive reference.
string strFileName;
private void btnReadInFile_Click(object sender, EventArgs e)
{
//select the file
OpenFileDialog ofdGetFile = new OpenFileDialog();
if (ofdGetFile.ShowDialog() == DialogResult.Cancel)
{
//cancel
MessageBox.Show("User Canceled");
return;
}
else
{
//open the file
StreamReader myStreamReader;
strFileName = ofdGetFile.FileName;
FileStream input = new FileStream(strFileName, FileMode.Open, FileAccess.Read);
myStreamReader = new StreamReader(input);
// other
MessageBox.Show("Reading Complete", "Done!", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
private void btnShowGrade_Click(object sender, EventArgs e)
{
if (strFileName != null)
{
String[][] nameSums = System.IO.File.ReadLines(strFileName)
.Select(l => l.Split(',')) // split the line
.GroupBy(arr => arr[0]) // group by name
.Select(grp => new String[]{
grp.Key,
grp.Sum(arr => int.Parse(arr[1])).ToString()})
.ToArray();
}
else
{
MessageBox.Show("You need to read in a file first.");
}
}
}
I feel like there has to be a better way to do this.
Thank you all so much for your help thus far! I am sure that the only reason this problem hasn't been resolved is my lack of communication skills.
Upvotes: 0
Views: 6343
Reputation: 460228
Edit according to your last edit:
identify each string to it's corresponding amount, and then find the sums in their own groups
It's still not clear what you want to achieve. You should have provided the desired result of your sample data. I assume the amount is the number and group is the name-group.
So for the Name
-group it would be 50+40+60=150
, DifferentName
=50
and AnotherName
=10
?
This creates a Dictionary of unique names and their according amounts:
Dictionary<String, int> nameSums =
System.IO.File.ReadLines(path) // read lines from file
.Select(l => l.Split(',')) // split the line
.GroupBy(arr => arr[0]) // group by name
.ToDictionary(grp => grp.Key, grp => grp.Sum(arr => int.Parse(arr[1])));
If you insist on an array approach, following creates and initializes a jagged array(array of arrays) with the name as first element and the sum as second:
String[][] nameSums = System.IO.File.ReadLines(path) // read lines from file
.Select(l => l.Split(',')) // split the line
.GroupBy(arr => arr[0]) // group by name
.Select(grp => new String[]{
grp.Key,
grp.Sum(arr => int.Parse(arr[1])).ToString()})
.ToArray();
first approach:
"make the numbers correspond to their specific names"
So i assume that you want the names that belong to each number. If this is true a Dictionary<String, List<String>>
would be the best choice:
var numNames = System.IO.File.ReadLines(path)
.Select(l => l.Split(','))
.GroupBy(arr => arr[1])
.ToDictionary(grp => grp.Key, grp => grp.Select(arr => arr[0]).ToList());
IEnumerable<String>
String[]
Dictionary
, the (now) unique numbers are the keys and the names are the values as List<String>
If you aren't familiar with dictionaries, you normally access them by the key, so if you want to know all names for the number "50"
:
List<String> names = numNames["50"];
foreach(String name in names)
Console.Write("name={0}", name);
Or if you want to iterate all:
foreach(var numName in numNames)
foreach(var name in numName.Value)
Console.Write("number={0} name={1}", numName.Key, name);
Upvotes: 1
Reputation: 8818
Why not use a Dictionary?
So,
Dictionary<string,int> namesAndAges = new Dictionary<string,int>();
String[] line = new String[2];
while(there's still xml to read)
{
aLineOfXml = blah; //read a line of xml however you were gonna do it
line = aLineOfXml.Split(',');
namesAndAges.Add(line[0],line[1]);
}
The first two lines in the while loop would be better condensed into one, but for clarity and because I didn't want to add any xml parsing code, i split it like that.
Upvotes: 0
Reputation: 15004
Your task is IO bound. Most likely you won't gain any benefit changing the code. Firstly, you should use profiler to find the bottleneck of your application.
If you have .Net 4, 4.5 or Silverlight use ReadLines method. It returns an iterator that represents a collection of lines. Snippet:
List<KeyValuePair<string, double> values = new List<KeyValuePair<string, double>();
var lines = File.ReadLines(myFile);
foreach (var line in lines)
{
var data = line.Split(',');
var x = data[0];
var y = Double.Parse(data[1], CultureInfo.InvariantCulture);
var pair = new KeyValuePair<string, double>(x, y);
values .Add(pair);
}
Upvotes: 0
Reputation: 68707
myArray = File.ReadAllLines(myFileName).Select(l => l.Split(',')).ToArray();
Note this will be a staggered array, not a 2 dimensional one. To create a 2 dimensional one, you could use
lines = File.ReadAllLines(myFileName).Select(l => l.Split(',')).ToArray();
myArray = new string[lines.Count(), 2];
for(int i = 0; i < lines.Length; i++)
{
myArray[i, 0] = lines[i, 0];
myArray[i, 1] = lines[i, 1];
}
Upvotes: 0