Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a List of objects, List<myObject> objectList, and each object contains a List of strings like so:

myObject: StringList( "A_1", "B_1", "C_1", "D_1", "E_1", "F_1" )  
myObject: StringList( "A_2", "B_2", "C_1", "D_2", "E_2", "F_1" )  
myObject: StringList( "A_2", "B_3", "C_1", "D_3", "E_2", "F_1" )  

I'm trying to merge the lists into a dictionary of: Dictionary<string, List<string>>, where the final results will look like so:

Dictionary: { [A:1,2]  [B:1,2,3]  [C:1]  [D:1,2,3]  [E:1,2]  [F:1] }

Here is what I have done, and it does work:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();

foreach (myObject result in objectList)
{
    foreach (var item in result.StringList)
    {
        string Key = item.Split('_')[0];
        string Value = item.Split('_')[1];

        List<string> sValue = new List<string>();
        bool exists = dict.TryGetValue(Key, out sValue);

        if (exists && !sValue.Contains(Value))
        {
            sValue.Add(Value);
            dict[Key] = sValue;
        }
        else if (!exists)
        {
            sValue = sValue ?? new List<string>();
            sValue.Add(Value);
            dict.Add(Key, sValue);
        }
    }
}

Is there a better way to do this, where I don't have to use two foreach loops? Is there a way to do it without using any foreach loops?

I have tried using lambda but this is as far as I got:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();

foreach (myObject result in objectList)
{
    dict = result.StringList.Select(x => x.Split('_'))
                            .GroupBy(x => x[0])
                            .ToDictionary(x => x.Key, x => x.Select(g => g[1]).ToList());
}

The problem is that the expression keeps overwriting any existing entries in the dictionary each time I iterate through the loop.

Is there a way to keep the existing entries, groupby the Key and add to the existing list of values but don't duplicate any values?

I think the answer lies in this part of the expression:

x => x.Select(g => g[1]).ToList()

but I'm not 100% sure.

share|improve this question

migrated from stackoverflow.com Nov 27 '13 at 16:33

This question came from our site for professional and enthusiast programmers.

1  
Did you try SelectMany? – Mike Cheel Nov 27 '13 at 16:28
up vote 7 down vote accepted

Just get rid of the outer foreach as well:

dict = objectList.SelectMany(x => x.StringList)
       .Select(x => x.Split('_'))
       .GroupBy(x => x[0])
       .ToDictionary(x => x.Key, x => x.Select(g => g[1]).Distinct().ToList());

SelectMany retrieves all the StringLists and flattens them into one single list:

"A_1", "B_1", ..., "F_1", "A_2", "B_2", ...
share|improve this answer
    
I think you want a distinct in there as well so that A is 1,2 rather than 1,2,2. – Chris Nov 27 '13 at 16:39
1  
x => x.Select(g => g[1]).Distinct().ToList() – Ahmed KRAIEM Nov 27 '13 at 16:40
1  
Note that Distinct destroys order, so it might be 1,2 or 2,1. – Tim S. Nov 27 '13 at 16:48
    
@Heinzi - Thanks so much! This works perfectly! Much simpler and more elegant. For the life of me, I couldn't figure this out...a million times thank you! – user3042376 Nov 27 '13 at 16:59
1  
@Groo Like a comment at my link says, "what you say could be true [that it preserves first-found order], but it would be a bad idea to rely on that behavior" (because it is documented as being an unordered sequence, you should treat it as such). Also, I don't know that objectList had it sorted to begin with, the example just happens to have it so (I think). – Tim S. Nov 27 '13 at 17:07

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.