Lancelot
Lancelot

Reputation: 2427

Linq query

I'm a big noob with Linq and trying to learn, but I'm hitting a blocking point here. I have a structure of type:

Dictionary<MyType, List<MyObj>>

And I would like to query with Linq that structure to extract all the MyObj instances that appear in more than one list within the dictionary.

What would such a query look like?

Thanks.

Upvotes: 0

Views: 261

Answers (2)

Bryan Watts
Bryan Watts

Reputation: 45445

from myObjectList in myObjectDictionary.Values
from myObject in myObjectList.Distinct()
group myObject by myObject into myObjectGroup
where myObjectGroup.Skip(1).Any()
select myObjectGroup.Key

The Distinct() on each list ensures MyObj instances which repeat solely in the same list are not reported.

Upvotes: 3

rmoore
rmoore

Reputation: 15393

You could do something like this:

var multipleObjs =
    MyObjDictionary.Values // Aggrigate all the List<MyObj> values into a single list
        .SelectMany(list => list) // Aggrigate all the MyObjs from each List<MyObj> into a single IEnumerable
        .GroupBy(obj => obj) // Group by the Obj itself (Or an ID or unique property on them if it exists)
        .Where(group => group.Count() >= 2) // Filter out any group with less then 2 objects
        .Select(group => group.Key); // Re-Select the objects using the key.

Edit
I Realized that this could also be read diffrently, such that it doesn't matter if the MyObj occurs multiple times in the same list, but only if it occurs multiple times in diffrent lists. In that case, when we are initally aggrigating the lists of MyObjs we can select Distinct values, or use a slightly diffrent query:

var multipleObjs =
    MyObjDictionary.Values // Aggrigate all the List<MyObj> values into a single list
        .SelectMany(v => v.Distinct()) // Aggrigate all distinct MyObjs from each List<MyObj> into a single IEnumerable
        .GroupBy(obj => obj) // Group by the Obj itself (Or an ID or unique property on them if it exists)
        .Where(group => group.Count() >= 2) // Filter out any group with less then 2 objects
        .Select(group => group.Key); // Re-Select the objects using the key.


var multipleObjs =
        MyObjDictionary.SelectMany(kvp => // Select from all the KeyValuePairs
            kvp.Value.Where(obj =>
                MyObjDictionary.Any(kvp2 => // Where any of the KeyValuePairs
                    (kvp.Key != kvp2.Key) // Is Not the current KeyValuePair
                    && kvp.Value.Contains(obj)))); // And also contains the same MyObj.

Upvotes: 1

Related Questions