[英]How to return a specific item in Distinct using EqualityComparer in C#
I have defined a CustomListComparer
which compares List<int> A
and List<int> B
and if Union
of the two lists equals at least on of the lists, considers them equal. 我已经定义了一个
CustomListComparer
,用于比较List<int> A
和List<int> B
,如果两个列表的Union
至少等于列表,则认为它们相等。
var distinctLists = MyLists.Distinct(new CustomListComparer()).ToList();
public bool Equals(Frame other)
{
var union = CustomList.Union(other.CustomList).ToList();
return union.SequenceEqual(CustomList) ||
union.SequenceEqual(other.CustomList);
}
For example, the below lists are equal: 例如,以下列表是相同的:
ListA = {1,2,3}
ListB = {1,2,3,4}
And the below lists are NOT: 以下列表不是:
ListA = {1,5}
ListB = {1,2,3,4}
Now all this works fine. 现在一切正常。 But here is my question: Which one of the Lists (A or B) gets into
distinctLists
? 但这是我的问题:哪一个列表(A或B)进入
distinctLists
? Do I have any say in that? 我有什么发言权吗? Or is it all handled by compiler itself?
或者这一切都由编译器本身处理?
What I mean is say that the EqualityComparer
considers both of the Lists equal. 我的意思是说
EqualityComparer
认为两个列表相等。 and adds one of them to distinctLists
. 并将其中一个添加到
distinctLists
。 Which one does it add? 它添加了哪一个? I want the list with more items to be added.
我想要添加更多项目的列表。
Distinct
always adds the first element which it see. Distinct
总是添加它看到的第一个元素。 So it depends on the order of the sequence which you passed in. 所以它取决于你传入的序列的顺序。
Source is fairly simple, which can be found here 来源相当简单,可以在这里找到
static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) {
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
If you need to return list with more elements, you need to roll your own. 如果您需要返回包含更多元素的列表,则需要自行滚动。 Worth noting that
Distinct
is lazy, but the implementation you're asking for will need a eager implementation. 值得注意的是,
Distinct
是懒惰的,但你要求的实现需要急切的实现。
static class MyDistinctExtensions
{
public static IEnumerable<T> DistinctMaxElements<T>(this IEnumerable<T> source, IEqualityComparer<T> comparer) where T : ICollection
{
Dictionary<T, List<T>> dictionary = new Dictionary<T, List<T>>(comparer);
foreach (var item in source)
{
List<T> list;
if (!dictionary.TryGetValue(item, out list))
{
list = new List<T>();
dictionary.Add(item, list);
}
list.Add(item);
}
foreach (var list in dictionary.Values)
{
yield return list.Select(x => new { List = x, Count = x.Count })
.OrderByDescending(x => x.Count)
.First().List;
}
}
}
Updated the answer with naive implementation, not tested though. 使用天真的实现更新了答案,但未经过测试。
Instead of Distinct
you can use GroupBy
with MaxBy
method:: 您可以将
GroupBy
与MaxBy
方法一起使用而不是Distinct
::
var distinctLists = MyLists.GroupBy(x => x, new CustomListComparer())
.Select(g => g.MaxBy(x => x.Count))
.ToList();
This will group lists using your comparer and select the list that has max item from each group. 这将使用比较器对列表进行分组,并选择每个组中包含最大项目的列表。
MaxBy
is quite useful in this situation, you can find it in MoreLINQ library. MaxBy
在这种情况下非常有用,您可以在MoreLINQ库中找到它。
Edit: Using pure LINQ: 编辑:使用纯LINQ:
var distinctLists = MyLists.GroupBy(x => x, new CustomListComparer())
.Select(g => g.First(x => x.Count == g.Max(l => l.Count)))
.ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.