Reputation: 84650
Let's say I have an IEnumerable
of key/value pairs, that contains duplicates. If I call ToLookup
on it and pass lambdas that select the key and the value, I'll end up with a Lookup
where all the keys are unique, but the lists of values can contain duplicates. Is there any good way to end up with a Lookup
where none of the lists of values contain duplicates, in a single LINQ query statement?
I can't call Distinct
on the original sequence it because the elements are duplicates by value but not by object identity, and Distinct
doesn't take a lambda for a selector that I could use.
Upvotes: 3
Views: 1264
Reputation: 117154
It seems rather like a trivial exercise if you introduce an anonymous intermediate object.
Try this:
var lookup =
sequence
.Select(x => new { x.Key, x.Value })
.Distinct()
.ToLookup(x => x.Key, x => x.Value);
Since you can call .Distinct()
on anonymous variables then this should work just fine.
Upvotes: 0
Reputation: 2042
You can use a little GroupBy
hack instead of Distinct
:
var lookup = source.GroupBy(i => get_unique_id(i),
(key, group) => group.First()).ToLookup(i => i.Key, i => i.Value);
GroupBy
will create groups based on the "unique value" you choose. The call to group.First
will only keep one element of that group. So you remove all others with the same "unique value" or "group criteria". This is basically an extended Distinct
.
get_unique_id
should return the same value for the same key/value combination and a different value otherwise.
Upvotes: 1
Reputation: 9477
You can use a GroupBy before building the Lookup in Combination with a select many. This doesnt feel so good however:
Something like this:
sequence.GroupBy(kvp => _getKey(kvp))
.SelectMany(grp => grp.Distinct()
.Select(value => new { grp.Key, Value = value}))
.ToLookUp(grp => grp.Key, grp=> grp.Value);
Alternative would be using a Dictionary, since I am not quite sure why you want to use lookup.
sequence.GroupBy(kvp => _getKey(kvp))
.Select(g => new { g.Key, Values = new HashSet<WhatEver>(g)})
.ToDictionary(v => v.Key, v => v.Values);
Alternative to Hashset would be providing an EqualityComparer with the Distinct()
public sealed class WhatEverComparer : IEqualityComparer<WhatEver>
{
... implement interface..
}
Then
sequence.GroupBy(kvp => _getKey(kvp))
.Select(g => new { g.Key, Values = g.Distinct(new WhatEvercomparer()).ToArray()})
.ToDictionary(v => v.Key, v => v.Values);
Upvotes: 1