Reputation: 87
Is there a way that I have a dictionary and I need to get only the pair that occurs more than once in Linq ? for example in
{1, "entries"},
{2, "images"},
{3, "views"},
{4, "images"},
{5, "results"},
{6, "images"},
{7, "entries"}
I get
{1, "entries"},
{2, "images"},
{6, "images"},
{7, "entries"}
Upvotes: 3
Views: 1525
Reputation: 2598
With these extension methods you have a (little bit) faster and general solution (works on all IEnumarable sources):
public static class Extensions
{
public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
{
var grouped = source.GroupBy(selector);
var moreThen1 = grouped.Where(i => i.IsMultiple());
return moreThen1.SelectMany(i => i);
}
public static bool IsMultiple<T>(this IEnumerable<T> source)
{
var enumerator = source.GetEnumerator();
return enumerator.MoveNext() && enumerator.MoveNext();
}
}
Fill the source:
// Create the source
var dictionary = new Dictionary<int, string>
{
{1, "entries"},
{2, "images"},
{3, "views"},
{4, "images"},
{5, "results"},
{6, "images"},
{7, "entries"}
};
Here are 3 options (each option is improved):
// More or less the same solution as other answers
var multiples1 = dictionary.GroupBy(p => p.Value)
.Where(g => g.Count() > 1)
.SelectMany(g => g);
// A little bit faster because IsMultiple does not enumerate all values
// (Count() iterates to the end, which is not needed in this case).
var multiples2 = dictionary.GroupBy(p => p.Value)
.Where(g => g.IsMultiple())
.SelectMany(g => g);
// Easy to read
var multiples3 = dictionary.Duplicates(p => p.Value);
Upvotes: 0
Reputation: 437386
If you mean only the values that occur more than once, you can do group the key/value pairs by value, filter out the groups with only one item and select the common group key (original value that appears multiple times) from what remains:
var multiples = dictionary.GroupBy(p => p.Value)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
If you want all pairs of keys/values where the values occur more than once, this variation will do it:
var multiples = dictionary.GroupBy(p => p.Value)
.Where(g => g.Count() > 1)
.SelectMany(g => g);
The only difference is in the last step, where after casting out groups with just one value the contents of all remaining groups are "unwrapped" into a single sequence of key/value pairs.
In the latter case, you can turn the results back into a dictionary (essentially filtering out values that appear only once) by following up with
.ToDictionary(p => p.Key, p => p.Value)
The last example, in query form:
var multiples = from pair in dictionary
group pair by pair.Value into grp
where grp.Count() > 1
from pair in grp select pair;
Upvotes: 13
Reputation: 18411
Dictionary<int,string> d = new Dictionary<int,string>();
d.Add(1, "entries");
d.Add(2, "images");
d.Add(3, "views");
d.Add(4, "images");
d.Add(5, "results");
d.Add(6, "images");
d.Add(7, "entries");
d.GroupBy(x => x.Value)
.Where(x=>x.Count()>1)
.SelectMany(x => x)
.ToDictionary
(
x => x.Key,
x=>x.Value
);
Upvotes: 0
Reputation: 117380
var res = dict.GroupBy(x => x.Value).Where(y => y.Count() > 1);
if you want to get a Dictionary:
var res = dict.GroupBy(x => x.Value)
.Where(y => y.Count() > 1)
.SelectMany(z => z)
.ToDictionary(k => k.Key, k => k.Value);
Upvotes: 2