3

I have a Dictionary(List, List(string)) (apologies, for some reason, this editor is not allowing me to type <>) which looks like the following:

Key: A --> Value:{1,2,3}
Key: B --> Value:{a,b,c}
Key: C --> Value:{Hi,Hello,Hola}

I would like to create a .csv file with Headers corresponding to my dictionary Keys, and 'Columns' corresponding to the List's.

So, for instance, First 'column in my csv file should be: column 'A', with values 1 2 3 Second 'column' in my csv file should be: column 'B', with values a b c, etc.. (Note that I would prefer that the ordering of the columns be kept, but it is ok if it's not)

Or in other words, since this will be a Comma Separated File, the First 'Row' (Headers) should be: A,B,C
2nd row: 1, a , Hi 3rd row: 2, b, Hello and 4th row: 3, c, Hola

What is the best way to achieve this in C#? I have tried researching this first, but most suggestions I seem to see online seem to not use a dictionary in the format Dictionary(List, List(string)).

I appreciate the help.

Nodame
  • 1,053
  • 3
  • 12
  • 18

2 Answers2

1

You can try this:

 static void Main(string[] args)
    {
        //Sample data declaration
        Dictionary<string, List<string>> data = new Dictionary<string, List<string>>();
        data.Add("Hello", new List<string>{"1", "2", "4"});
        data.Add("Foo", new List<string> { "3", "4", "7" });
        data.Add("World", new List<string> { "3", "4", "7" });

        DicToExcel(data, @"D:\my.csv");

    }

Here comes the logic:

    public static void DicToExcel(Dictionary<string, List<string>> dict, string path)
    {
            //We will put all results here in StringBuilder and just append everything
            StringBuilder sb = new StringBuilder();

            //The key will be our header
            String csv = String.Join(",",
                   dict.Select(d => d.Key));
            sb.Append(csv + Environment.NewLine);

            //We will take every string by element position
            String csv1 = String.Join(",",
                   dict.Select(d => string.Join(",", d.Value.First().Take(1))));
            sb.Append(csv1 + Environment.NewLine);

            String csv2 = String.Join(",",
                   dict.Select(d => string.Join(",", d.Value.Skip(1).Take(1))));
            sb.Append(csv2+ Environment.NewLine);

            String csv3 = String.Join(",",
                 dict.Select(d => string.Join(",", d.Value.Skip(2).Take(1))));
            sb.Append(csv3);

            //Write the file
            System.IO.File.WriteAllText(path, sb.ToString());

    }

The result would be:

Hello   Foo     World
1       3       3
2       4       4
4       7       7
Willy David Jr
  • 8,604
  • 6
  • 46
  • 57
  • You are welcome! If this answers your question, you can now accept it as an answer for other people's reference as well @Nodame – Willy David Jr Mar 09 '17 at 01:59
0

One solution would be to transform your map into a list of lists. The outer list corresponds to the file, the inner lists correspond to rows. Once you have that output becomes easy.

In your example, the new data structure would be:

[[A,B,C]
 [1,a,Hi]
 [2,b,Hello]
 [3,c,Hola]]

A set of nested loops over your map and data will allow you to do the transform.

Aaron
  • 874
  • 3
  • 17
  • 34