【问题标题】:Linq distinct based on two columnsLinq 基于两列不同
【发布时间】:2015-08-13 13:11:15
【问题描述】:

我有一个要求,我需要在 2 列中获取具有相同组合的唯一记录。 我的数据就像 CA(A 列) 和 CB(B 列) 有一些数据

CACB
12
12
34
5@98765433306
@1
16
16
51

假设我需要从两个应该是唯一的列中获取值为 1 的记录。

所以,我的最终结果应该是这样的:

12
16
51

这里我不应该得到记录2,1,因为该组合在第一条记录中已经存在1,2

这是我尝试过的查询:

var recentchats = (from s in MessagesCollection.AsQueryable()
                    where (s.@from == mytopic || s.to == mytopic) 
                    orderby s._id descending
                    select s).DistinctBy(x => x.from).Take(10).ToList();

我用moreLinq 扩展DistinctBy,因为我需要整个记录。(抱歉格式和英文不好!!!)

这里,我的实际需求是获取用户最近的聊天记录

【问题讨论】:

    标签: c# linq morelinq


    【解决方案1】:

    由于where 已经确保两个值之一始终相同,您可以使用distinctBy 中的和。 (例如 1 + 2 等于 2 + 1)

    DistinctBy(x => x.from + x.to)
    

    如果没有 where,您仍然可以使用 Min 和 Max 来获得唯一的对。

    DistinctBy(x => new { Min=Math.Min(x.from, x.to), Max=Math.Max(x.from, x.to) })
    

    【讨论】:

      【解决方案2】:

      所以你需要一种方法来根据多列检测重复并且顺序无关紧要?你可以使用这个类:

      public class MultiFieldIgnoreOrderComparer : IEquatable<IEnumerable<object>>, IEqualityComparer<IEnumerable<object>>
      {
          private IEnumerable<object> objects;
      
          public MultiFieldIgnoreOrderComparer(IEnumerable<object> objects)
          {
              this.objects = objects;
          }
      
          public bool Equals(IEnumerable<object> x, IEnumerable<object> y)
          {
              return x.All(y.Contains);
          }
      
          public int GetHashCode(IEnumerable<object> objects)
          {
              unchecked
              {
                  int detailHash = 0;
                  unchecked
                  {
                      // order doesn't matter, so we need to order:
                      foreach (object obj in objects.OrderBy(x => x))
                          detailHash = 17 * detailHash + (obj == null ? 0 : obj.GetHashCode());
                  }
                  return detailHash;
              }
          }
      
          public override int GetHashCode()
          {
              return GetHashCode(this.objects);
          }
      
          public override bool Equals(object obj)
          {
              MultiFieldIgnoreOrderComparer other = obj as MultiFieldIgnoreOrderComparer;
              if (other == null) return false;
              return this.Equals(this.objects, other.objects);
          }
      
          public bool Equals(IEnumerable<object> other)
          {
              return this.Equals(this.objects, other);
          }
      }
      

      你可以这样使用:

      var recentchats = MessagesCollection.AsQueryable()
          .Where(x => x.CA == 1 || x.CB == 1)
          .GroupBy(x => new MultiFieldIgnoreOrderComparer(new[] { x.CA, x.CB }))
          .Select(g => g.First())
          .ToList();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多