3

有没有办法让我有一本字典,我只需要获取在 Linq 中多次出现的那对?例如在

{1, "entries"},  
{2, "images"},
{3, "views"},
{4, "images"},
{5, "results"},
{6, "images"},
{7, "entries"}

我明白了

{1, "entries"}, 
{2, "images"},
{6, "images"},
{7, "entries"}
4

4 回答 4

13

如果您仅指多次出现的值,则可以按值对键/值对进行分组,过滤掉只有一项的组,然后从剩余的部分中选择公共组键(多次出现的原始值):

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;
于 2013-08-09T20:15:29.230 回答
2
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);
于 2013-08-09T20:16:32.700 回答
0
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
 );
于 2013-08-09T20:19:14.927 回答
0

使用这些扩展方法,您可以获得(一点点)更快且通用的解决方案(适用于所有 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);
于 2013-08-09T21:01:11.987 回答