【发布时间】:2019-01-07 18:12:25
【问题描述】:
类似于question,但改写为 Linq:
您可以使用Enumerable<T>.Any() 来测试可枚举是否包含数据。但是,在不使用昂贵的计数操作的情况下,测试可枚举对象是否包含单个值(即Enumerable<T>.Count() == 1)或大于单个值(即Enumerable<T>.Count() > 1)的有效方法是什么?
【问题讨论】:
类似于question,但改写为 Linq:
您可以使用Enumerable<T>.Any() 来测试可枚举是否包含数据。但是,在不使用昂贵的计数操作的情况下,测试可枚举对象是否包含单个值(即Enumerable<T>.Count() == 1)或大于单个值(即Enumerable<T>.Count() > 1)的有效方法是什么?
【问题讨论】:
int constrainedCount = yourSequence.Take(2).Count();
// if constrainedCount == 0 then the sequence is empty
// if constrainedCount == 1 then the sequence contains a single element
// if constrainedCount == 2 then the sequence has more than one element
【讨论】:
一种方法是编写一个新的扩展方法
public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
using (var enumerator = enumerable.GetEnumerator()) {
if (!enumerator.MoveNext()) {
return false;
}
return !enumerator.MoveNext();
}
}
【讨论】:
此代码采用 LukeH 的出色答案并将其包装为 IEnumerable 扩展名,以便您的代码可以处理 None、One 和 Many 而不是 0、1 和 @ 987654327@.
public enum Multiplicity
{
None,
One,
Many,
}
在静态类中,例如EnumerableExtensions:
public static Multiplicity Multiplicity<TElement>(this IEnumerable<TElement> @this)
{
switch (@this.Take(2).Count())
{
case 0: return General.Multiplicity.None;
case 1: return General.Multiplicity.One;
case 2: return General.Multiplicity.Many;
default: throw new Exception("WTF‽");
}
}
【讨论】:
另一种方式:
bool containsMoreThanOneElement = yourSequence.Skip(1).Any();
或者正好是 1 个元素:
bool containsOneElement = yourSequence.Any() && !yourSequence.Skip(1).Any();
【讨论】:
seq.Any() 和seq.Skip(1).Any() 总结成了一个很好的声明。
高效Count() == n测试:
public static bool CountIsEqualTo<T>(this IEnumerable<T> enumerable, int c)
{
using (var enumerator = enumerable.GetEnumerator())
{
for(var i = 0; i < c ; i++)
if (!enumerator.MoveNext())
return false;
return !enumerator.MoveNext();
}
}
【讨论】:
使用 linq to objects,如果有多个元素,SingleOrDefault 会抛出,所以如果你自己滚动,你可能是最好的。
编辑:现在我看到了 LukeH 的回答,我不得不说我更喜欢它。希望我自己能想到!
【讨论】:
SingleOrDefault 会抛出。如果没有元素,它只返回default(T)。
SingleOrDefault 的评论是正确的。 Single 和SingleOrDefault 的区别不在于是否扔,而在于何时。
bool hasTwo = yourSequence.ElementAtOrDefault(1) != default(T);
...如果类的值可以为空,这可能对我们有用。
【讨论】: