Linq基于两列不同

时间:2015-08-13 13:11:16

标签: c# linq morelinq

我有一个要求,我需要在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

此处我不应该获取记录21,因为该组合已在第一条记录中以12的形式存在。

以下是我尝试的查询:

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扩展程序,因为我需要整个记录。(抱歉格式错误和英文!!!)

在这里,我的实际要求是获取用户最近的聊天

2 个答案:

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

答案 1 :(得分:0)

所以你需要一种方法来检测多列的重复项,顺序并不重要?你可以使用这个类:

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