Get objects from dictionary with equal properties values for every Key

时间:2018-07-25 08:16:50

标签: c# linq

I have such class:

public class Item
{
    public int Id {get;set;}
    public string A {get;set;}
    public string B {get;set;}
    public string C {get;set;}
}

And now I have an example dictionary which looks like this:

var dict = new Dictionary<<int, List<Item>>()
{
    { 
       1, 
       new List<Item>() 
       { 
          new Item { Id = 1, A = "aaa", B = "bbb", C = "ccc" }, 
          new Item { Id = 2, A = "q", B = "w", C = "e" }
       } 
    },
    { 
       2, 
       new List<Item>() 
       { 
          new Item { Id = 3, A = "aaa", B = "bbb", C = "ccc" }, 
          new Item { Id = 4, A = "qqq", B = "www", C = "eee" }
       } 
    },
    { 
       3, 
       new List<Item>() 
       { 
          new Item { Id = 1, A = "aaa", B = "bbb", C = "ccc" }, 
          new Item { Id = 5, A = "some", B = "other", C = "case" }
       } 
    },
};

What I need to do is to find all Item's which have equal values on properties A, B, C for ALL keys, so as an output there should be an IEnumerable<Item> / List<Item>.

For the example above, the output would contain a single Item element with values:

A = "aaa", B = "bbb", C = "ccc"

because for each dictionary key an Item object with those exact values exist. Id for this object could be taken from first Item that matches, so it could be equal to 1

How would a LINQ query look for this?

3 个答案:

答案 0 :(得分:2)

您要查找的查询看起来像这样:

dict .SelectMany(d => d.Value) .Where(d => dict.All(di => di.Value.Any(v => v.A == d.A && v.B == d.B && v.C == d.C))) .GroupBy(d => new { A = d.A, B = d.B, C = d.C }) .Select(d => d.Key) .ToList();

快速说明:

  1. 列出所有项目
  2. 遍历所有项,仅保留所有具有该项的字典项(基于属性A,B和C)
  3. 将属性A,B,C上的项目分组(因为这些项目的ID不同)
  4. 选择密钥(属性为A,B,C的匿名类)

答案 1 :(得分:1)

另一种解决方案是使用Aggregate,并在Item类中覆盖GetHash,如下所示:

dict.SelectMany(x => x.Value)
    .Aggregate(new Dictionary<Item, int>(), (map, item1) => 
        {
            if (map.ContainsKey(item1))
                map[item1]++;
            else map[item1] = 0;
            return map;
        })
   .Where(y => y.Value > 0)
   .Select(pair =>pair.Key);

项目覆盖:

    public bool Equals(Item other)
    {
        return A == other?.A && B == other.B && C == other.C;
    }

    public override int GetHashCode()
    {
        int hash = 13;
        hash = (hash * 7) + A.GetHashCode();
        hash = (hash * 7) + B.GetHashCode();
        hash = (hash * 7) + C.GetHashCode();

        return hash;
    }

答案 2 :(得分:1)

使用IEqualityComparer,您可以轻松地: 选择所有“值”,“组”,“唯一过滤器”,“选择项目”。

var flatAllValues = dict.SelectMany(x => x.Value).ToList();
var group = flatAllValues
     .GroupBy(p => p, new ItemComparer())
     .Where(g => g.Count() > 1)
     .Select(g =>  g.Key);

IEqualityComparer实现:

class ItemComparer : IEqualityComparer<Item>
{
    public bool Equals(Item i1, Item i2)
    {
        if (i1 == null && i2 == null)
            return true;
        else if (i2 == null | i1 == null)
            return false;
        else if (i2.A == i1.A
            && i2.B == i1.B
            && i2.C == i1.C)
            return true;
        else
            return false;
    }

    public int GetHashCode(Item i)
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + i.A.GetHashCode();
            hash = hash * 23 + i.B.GetHashCode();
            hash = hash * 23 + i.C.GetHashCode();
            return hash;
        }
    }
}