基于两列的Linq不同

本文关键字:不同 Linq 于两列 | 更新日期: 2023-09-27 18:07:51

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

CA CB
1 2
1 2
3 4
5 6
2 1
1 6
1 6
5 1

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

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

1 2
1 6
5 1

这里我不应该得到记录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,因为我需要整个记录。(抱歉格式和英文不好!!)

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

基于两列的Linq不同

由于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) })

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

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();