Most efficient way to split a 2D array?

这一生的挚爱 提交于 2019-12-23 05:59:04

问题


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.


回答1:


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];
}



回答2:


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());
  1. The lines are read from file as IEnumerable<String>
  2. then each line is split by comma to a String[]
  3. these are grouped by the second element(the number) to get unique numbers and their names
  4. the result will be used to create a 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);



回答3:


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



回答4:


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.



来源:https://stackoverflow.com/questions/10356060/most-efficient-way-to-split-a-2d-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!