C#Linq GroupBy - 具体标准

时间:2018-05-27 02:07:57

标签: c# linq

我有下表,我想分组,

Id   NameId   ValueId
1       1       4
1       10      18
1       9       15

2       1       4
2       10      17
2       9       0

3       1       5
3       9       16
3       10      18

4       1       5
4       10      18
4       9       16

5       1       4
5       10      17
5       9       0

结果应该与具有类似ValueId的Id分组,用于所有相应的NameId

输出

GroupId                                      Id          ValueId
fed1afcc-a778-48ef-9ee5-4b70886ce67c          1           4,18,15
a31055df-2e4e-472e-9301-e0e0a4e99f1e          2,5         4,17,0
8b9b3dca-4ce0-4cae-a870-1d1026bd608a          3,4         5,18,16

我实际上并不需要它们连接在一起,它只是表示输出应该如何分组。

我使用嵌套for循环完成了一个有效的实现,它将每个实体与后续实体进行比较,并检查所有值。我是在做一些可以在Linq中简单实现的事情吗?

或者如何在Linq中完成?

我当前代码的最小版本

  var tableResult = _repository.GetData().OrderBy(x =>x.NameId).ToList();
  var ids = tableResult.Select(x => x.id).Distinct().ToList();
  var listOfProductGroup = new List<ProductGroup>();
  for (int i = 0; i < ids.Count; i++)
  {   
       var currentId = ids[i];
       var currentEntity = tableResult.Where(x => x.id == currentId).ToList();
       var productGroup = new ProductGroup(Guid.NewGuid(), currentProductId);

      for (int j = i + 1; j < ids.Count; j++)
      {
         var subsequentId = ids[j];
         var subsequentEntity = tableResult.Where(x => x.id == subsequentId ).ToList();
         //This is my extension method which does the comparison
         if(currentEntity.EqualsAll(subsequentEntity))
         {
            productGroup.Id.Add(subsequentId );
            //am removing the product to avoid extra loop
            ids.RemoveAt(j);
            //adjust the index to match the removed product
            j = j - 1;
         }
      }
  }
  listOfProductGroup.Add(productGroup);


public class ProductGroup
{

    public ProductGroup(Guid groupId, int id)
    {
        GroupId= groupId;
        Id= new List<int>()
        {
            id
        };
    }
    public Guid GroupId{ get; set; }
    public IList<int> Id { get; set; }
}

1 个答案:

答案 0 :(得分:2)

这样的事情,也许是:

class DictionaryComparer : IEqualityComparer<Dictionary<int, int>>
{
    public bool Equals(Dictionary<int, int> x, Dictionary<int, int> y)
    {
        return x.Count == y.Count && !x.Except(y).Any();
    }

    public int GetHashCode(Dictionary<int, int> obj)
    {
        int hash = 0;
        foreach (var kvp in obj.OrderBy(x => x.Key))
        {
            hash = hash ^ EqualityComparer<KeyValuePair<int, int>>.Default.GetHashCode(kvp);
        }
        return hash;
    }
}
class Thing
{
    public int Id { get; set; }
    public int NameId { get; set; }
    public int ValueId { get; set; }

    public Thing(int id, int nameId, int valueId)
    {
        Id = id;
        NameId = nameId;
        ValueId = valueId;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var data = new Thing[]
        {
            new Thing(1,       1,       4),
            new Thing(1,       10,      18),
            new Thing(1,       9,       15),
            new Thing(2,       1,       4),
            new Thing(2,       10,      17),
            new Thing(2,       9,       0),
            new Thing(3,       1,       5),
            new Thing(3,       9,       16),
            new Thing(3,       10,      18),
            new Thing(4,       1,       5),
            new Thing(4,       10,      18),
            new Thing(4,       9,       16),
            new Thing(5,       1,       4),
            new Thing(5,       10,      17),
            new Thing(5,       9,       0),
        };

        var @as = data.GroupBy(x => x.Id)
            .Select(x => new {Id = x.Key, Data = x.ToDictionary(t => t.NameId, t => t.ValueId)})
            .GroupBy(x => x.Data, x => x.Id, new DictionaryComparer());

        foreach (var a in @as)
        {
            Console.WriteLine("{0} {1}", string.Join(",", a), string.Join(",", a.Key.Values));
        }

        Console.ReadKey();
    }
}