【发布时间】:2013-09-25 15:37:32
【问题描述】:
这样的列表:
int[] numbers = {1,2,2,3,3,4,4,5};
我可以使用 Distinct() 函数删除重复项,因此列表将显示为:1,2,3,4,5
但是,我想要相反的。我希望它删除所有重复的数字,留下唯一的数字。
因此列表将显示为:1,5。
如何做到这一点?
【问题讨论】:
标签: c#
这样的列表:
int[] numbers = {1,2,2,3,3,4,4,5};
我可以使用 Distinct() 函数删除重复项,因此列表将显示为:1,2,3,4,5
但是,我想要相反的。我希望它删除所有重复的数字,留下唯一的数字。
因此列表将显示为:1,5。
如何做到这一点?
【问题讨论】:
标签: c#
值得一提的是,一个检查序列是否包含超过 N 元素的扩展:
public static bool CountMoreThan<TSource>(this IEnumerable<TSource> source, int num)
{
if (source == null)
throw new ArgumentNullException("source");
if (num < 0)
throw new ArgumentException("num must be greater or equal 0", "num");
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Count > num;
}
ICollection collection2 = source as ICollection;
if (collection2 != null)
{
return collection2.Count > num;
}
int count = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (++count <= num + 1)
if (!enumerator.MoveNext())
return false;
}
return true;
}
现在变得简单高效:
var allUniques = numbers.GroupBy(i => i)
.Where(group => !group.CountMoreThan(1))
.Select(group => group.Key).ToList();
或者,正如@KingKing 对乔恩的回答所评论的那样:
var allUniques = numbers.GroupBy(i => i)
.Where(group => !group.Skip(1).Any())
.Select(group => group.Key).ToList();
【讨论】:
.Skip(1).Any() 而不是.Count() > 1。
一种方法是
var singles = numbers.GroupBy(n => n)
.Where(g => g.Count() == 1)
.Select(g => g.Key); // add .ToArray() etc as required
【讨论】:
!g.Skip(1).Any() 在我看来会比g.Count()==1稍微好一点。
.Count() 是最好的。我认为我曾在某个时候对此进行过基准测试,但我现在找不到它,所以我只有 99% 的把握。
GroupBy 正在使用延迟执行,但 Count() 将完全执行它。
Count。感谢您的回复。
.Count() 在这种情况下是恒定的时间。
var cleanArray = numbers.GroupBy(x=>x)
.Where(x=>x.Count() == 1)
.SelectMany(x=>x)
.ToArray();
【讨论】: