0

This is a follow up question to Getting specific row and column value in .csv file in c# .

I have a bunch of .csv-files in a specific folder that I want to be able to read values from:

cars.csv
planes.csv
tanks.csv

What I want to do is, for my csvfiles class that I have created, to store in it he content of each one of the csv files in a large array like the one I have thanks to the help I got mentioned above:

  string[][] m_Data = File
    .ReadLines(@"c:\MyFile.csv")
    .Where(line => !string.IsNullOrWhiteSpace(line)) 
    .Skip(1)
    .Select(line => line.Split(','))
    .ToArray();

I would like is to save the content of all files in some kind of equivalent to a C++ std::map<string, std::map<int, std::map<int, double>>> FileMap where I can search for the file name, like car, and then be able to get a specific value from a specific file at a specific position like in the C++ code below:

double GetVal(string std::filename, int row, int column)
{
   return FileMap[filename][row][column]
}

How do I do that in C#?

edit: Content of one of the .csv-files:

Index,Time,value,,Index,Time,value
1,0,20,,1,0,120
2,1,30,,2,1,90
KGB91
  • 630
  • 2
  • 6
  • 24
  • Just use generic dictionaries – Jonathan Alfaro Mar 05 '20 at 22:32
  • How do I convert `string[][] m_Data = File` to a dictionary then? I need to know how to fill the dictionary too. – KGB91 Mar 05 '20 at 22:34
  • if you provide a sample file i could write some some code to demo. you basically have to group by then call todictionary. using linq is rather simple – Jonathan Alfaro Mar 05 '20 at 22:41
  • Sorry! Added a sample file. It can be extended to the right with several arms and deepening on the time horizon it can be extended downwards. – KGB91 Mar 05 '20 at 22:45

1 Answers1

2

You could have a class like this that has a _dictionary field of the type you can see in the below example, then you extract the data from a file, store them in an NxM array of strings and then you call PopulateDictionary method to add the data to the _dictionary field. You repeat this process for each file. You can then call method to read the values from the _dictionary field.

class Program
{
    static Dictionary<string, Dictionary<int, Dictionary<int, double>>> _dictionary = 
                                new Dictionary<string, Dictionary<int, Dictionary<int, double>>>();


    static void PopulateDictionary(string filename, string[][] data)
    {
        _dictionary.Add(filename, new Dictionary<int, Dictionary<int, double>>());

        for (int i = 0; i < data.Length; i++)
        {
            _dictionary[filename].Add(i, new Dictionary<int, double>());

            for (int j = 0; j < data[i].Length; j++)
            {
                _dictionary[filename][i].Add(j, double.Parse(data[i][j]));
            }
        }
    }

    static double GetVal(string filename, int row, int column)
    {
        return _dictionary[filename][row][column];
    }

    static void Main(string[] args)
    {
        List<string> csvData1 = new List<string>() { "23, 5, 7", "40, 15" };
        List<string> csvData2 = new List<string>() { "40, 80, 112", "13", "20, 65, 9" };

        string[][] dataArr1 = csvData1.Select(x => x.Split(',')).ToArray();
        string[][] dataArr2 = csvData2.Select(x => x.Split(',')).ToArray();
        PopulateDictionary("f1", dataArr1);
        PopulateDictionary("f2", dataArr2);

        Console.WriteLine(GetVal("f1", 0, 0));
        Console.WriteLine(GetVal("f2", 1, 0));
        Console.WriteLine(GetVal("f2", 2, 2));

        Console.ReadKey();
    }
}

I've included a Main method for simulating the creation of a dictionary that you can easily run to check if my solution suits your needs. The lists represent the lines you should read from the csv files. The matrixes of string represent the data organized by rows and columns that contain the double values in string representation. Then, I simulate the adding of the values to the dictionary giving the filename (you should use the name of the csv files from which you extract the data) and the matrix representing the rows and the columns. At the end I read the first value found at the first column of the first row in the first list, then the single element at the unique column of the second row in the second list and at last the last column of the last row in the second list.

KGB91
  • 630
  • 2
  • 6
  • 24
claudiom248
  • 346
  • 2
  • 9
  • The question is how to create the `Dictionary>>` You've just created the outer dictionary, but not any of the internal ones. – Enigmativity Mar 05 '20 at 22:27
  • You were right, I have added the method to populate the dictionary with the data taken from the csv. – claudiom248 Mar 05 '20 at 22:41
  • Seems good, but i get `"Error CS1503 Argument 1: cannot convert from 'string' to 'char'` edit "" to '' in `x.Split`. – KGB91 Mar 05 '20 at 23:02
  • You should be able to call string.Split with both single quotes and double quotes. – claudiom248 Mar 05 '20 at 23:04
  • Okay i was not and don't know why... Well thanks for the help, gonna test it out tomorrow for real. – KGB91 Mar 05 '20 at 23:09
  • Ok, let me know if my solution will be useful. – claudiom248 Mar 05 '20 at 23:18
  • If I want to open a specific `.csv` file and then give it to `PopulateDictionary`, how do I do that? – KGB91 Mar 06 '20 at 07:57
  • 1
    For each of your csv files, you read it one at the time, then you apply the logic to move the data in the matrix and then you pass the name of the file and the matrix to populate the dictionary. You've already implemented the logic to read a file and to move its data to string[][] as you wrote. – claudiom248 Mar 06 '20 at 08:02
  • 1
    You'are welcome. I'm glad my solution has been useful. – claudiom248 Mar 06 '20 at 11:35