Search code examples
c#linqcollectionsgeneric-collections

Split a collection with repeated values into ranges, C#


I have the two lists:

List<string> keys = new List<string>() 
{ 
    "REPORTMONTH", 
    "CONTRACT", "DATE", "AMOUNT",
    "CONTRACT", "DATE", "AMOUNT"
};

List<string> values = new List<string>() 
{   
    "01", 
    "ABC123", "01022014", "300.00", 
    "DEF345", "03042014", "400.00"
};

The first list represents keywords which can have certain repetitions. The second list contains values associated with the keys in the first list (by index). The result output should be of type List<Dictionary<string, string>> and contain:

1st dictionary

key                   value
"REPORTMONTH"        "01"
"CONTRACT"           "ABC123"
"DATE"               "01022014"
"AMOUNT"             "300.00"

2nd dictionary

key                  value
"REPORTMONTH"        "01"
"CONTRACT"           "DEF345"
"DATE"               "03042014"
"AMOUNT"             "400.00"

I.e. the keys that do not repeat should present in both dictionaries, the rest should be splitted into dictionaries with associated values. Note, there can be no repeptitions at all, or more than 2.

Sorry, I cannot show my attempts for this question, because I'm not sure how to start. Maybe using LINQ and grouping can solve the problem?

Thank you.


Solution

  • You could do this in a way that does not look that elegant, requiring some loops. Note that this will also work if there are more than 2 dictionaries.

    public static void Main(params string[] args)
    {
        List<string> keys = new List<string>()  { 
            "REPORTMONTH", 
            "CONTRACT", "DATE", "AMOUNT",
            "CONTRACT", "DATE", "AMOUNT"
        };
    
        List<string> values = new List<string>() {   
            "01", 
            "ABC123", "01022014", "300.00", 
            "DEF345", "03042014", "400.00"
        }; 
    
        var pairs = keys.Select((key, ndx) => new { Key = key, Value = values[ndx] });
        var groups = pairs.GroupBy(e => e.Key)
            .ToDictionary(g => g.Key, g => g.Select(kvp => kvp.Value).ToArray());
        var dictionaries = new Dictionary<string, string>[groups.Max(g => g.Value.Length)];
    
        for (var i = 0; i < dictionaries.Length; i++)
        {
            dictionaries[i] = new Dictionary<string,string>();
            foreach (var g in groups) 
            {
                if (g.Value.Length == 1)
                    dictionaries[i][g.Key] = g.Value[0];
                else if (g.Value.Length > i)
                    dictionaries[i][g.Key] = g.Value[i];
            }
        }
    
        // print content
        for (var i = 0; i < dictionaries.Length; i++)
        {
            Console.WriteLine("Dictionary {0}:", i + 1);
            Console.WriteLine(string.Join(Environment.NewLine, dictionaries[i].Select(e => string.Format("{0} = {1}", e.Key, e.Value))));
            Console.WriteLine();
        }
        Console.ReadLine();
    }