有没有办法让我有一本字典,我只需要获取在 Linq 中多次出现的那对?例如在
{1, "entries"},
{2, "images"},
{3, "views"},
{4, "images"},
{5, "results"},
{6, "images"},
{7, "entries"}
我明白了
{1, "entries"},
{2, "images"},
{6, "images"},
{7, "entries"}
如果您仅指多次出现的值,则可以按值对键/值对进行分组,过滤掉只有一项的组,然后从剩余的部分中选择公共组键(多次出现的原始值):
var multiples = dictionary.GroupBy(p => p.Value)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
如果您想要值多次出现的所有键/值对,则此变体将执行此操作:
var multiples = dictionary.GroupBy(p => p.Value)
.Where(g => g.Count() > 1)
.SelectMany(g => g);
唯一的区别是在最后一步中,在剔除只有一个值的组之后,所有剩余组的内容都被“解包”成一个键/值对序列。
在后一种情况下,您可以通过跟进将结果转换回字典(基本上过滤掉只出现一次的值)
.ToDictionary(p => p.Key, p => p.Value)
最后一个示例,以查询形式:
var multiples = from pair in dictionary
group pair by pair.Value into grp
where grp.Count() > 1
from pair in grp select pair;
var res = dict.GroupBy(x => x.Value).Where(y => y.Count() > 1);
如果你想得到一个字典:
var res = dict.GroupBy(x => x.Value)
.Where(y => y.Count() > 1)
.SelectMany(z => z)
.ToDictionary(k => k.Key, k => k.Value);
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
);
使用这些扩展方法,您可以获得(一点点)更快且通用的解决方案(适用于所有 IEnumarable 源):
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();
}
}
填写来源:
// Create the source
var dictionary = new Dictionary<int, string>
{
{1, "entries"},
{2, "images"},
{3, "views"},
{4, "images"},
{5, "results"},
{6, "images"},
{7, "entries"}
};
这里有 3 个选项(每个选项都有改进):
// 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);