在 C# 中,使用 Linq,如果我想检查集合是否有任何元素,我可以这样做:
someCollection.Any()
哪个更好
someCollection.Count() > 0
由于后者会计算集合中的所有项目,因此当我并不真正关心有多少项目时,我只想知道是否有。
是否有等效的方法可以检查集合是否包含多个项目?像这样的东西:
someCollection.Many()
而不是必须做
someCollection.Count() > 1
我知道这是一个愚蠢的问题,而且根据我的研究,它看起来并不存在。但由于它是我经常使用的东西,我想我应该向社区仔细检查一下。
谢谢
最佳答案
根据我的评论:
首先,您应该检查是否 IEnumerable<T> source
实际上是 IReadOnlyCollection<T>
或ICollection<T>
因为那有一个 .Count
您可以使用的属性 - 这比任何迭代都更好。
假设您的IEnumerable<T>
没有O(1)
.Count
属性,如果您想查看是否有至少 1 个元素(即“至少 2 个或更多”),则使用 source.Take(2).Count() == 2
或source.Skip(1).Any()
.
像这样:
public static Boolean Many<T>( this IEnumerable<T> source )
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( source is ICollection<T> col ) return col.Count >= 2;
else if( source is IReadOnlyCollection<T> roCol ) return roCol.Count >= 2;
return source.Take(2).Count() == 2;
}
如果您想提高效率,请进行手动迭代:
public static Boolean Many<T>( this IEnumerable<T> source )
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( source is ICollection<T> col ) return col.Count >= 2;
else if( source is IReadOnlyCollection<T> roCol ) return roCol.Count >= 2;
Int32 count = 0;
using( IEnumerator<T> iter = source.GetEnumerator() )
{
while( iter.MoveNext() && count < 2 )
{
count += 1;
}
}
return count == 2;
}
如果您想提高效率,请允许消费者提供非盒装枚举器(例如 List<T>.Enumerator
):
public static Boolean Many<TEnumerable,TEnumerator,TElement>( /*this*/ TEnumerable source, Func<TEnumerable,TEnumerator> getEnumerator )
where TEnumerable : IEnumerable<TElement>
where TEnumerator : IEnumerator<TElement>
{
if( source is null ) throw new ArgumentNullException(nameof(source));
if( getEnumerator is null ) throw new ArgumentNullException(nameof(getEnumerator));
//
if ( source is ICollection<TElement> col ) return col .Count >= 2;
else if( source is IReadOnlyCollection<TElement> roCol ) return roCol.Count >= 2;
Int32 count = 0;
using( TEnumerator iter = getEnumerator( source ) )
{
while( iter.MoveNext() && count < 2 )
{
count += 1;
}
}
return count == 2;
}
像这样使用:
List<String> listOfStrings = new List<String>() { ... };
if( listOfStrings.Many</*TEnumerable:*/ List<String>, /*TEnumerator:*/ List<String>.Enumerator, /*TElement:*/ String >( l => l.GetEnumerator() ) )
{
}
- 是的,这很丑……很不幸,but C# still doesn't support this level of generic type-inference - 也不支持部分通用参数应用。
list.GetEnumerator()
需要部分,因为它是传递struct
的唯一方法基于枚举器转换为通用代码,无需装箱(至少不是没有反射)。
关于c# - 当集合有多个项目时,相当于 Linq 的 Any() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73443067/