字典C中值的出现#

时间:2013-08-09 20:13:19

标签: c# linq

有没有一种方法可以让我拥有一本字典,而我只需要获得在Linq中不止一次出现的那对 ? 例如在

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

我得到了

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

4 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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);

答案 2 :(得分: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
 );

答案 3 :(得分: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);