当集合有多个项目时,相当于Linq的Any()函数

c3frrgcw  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(157)

在C#中,如果我想使用Linq检查集合中是否有任何元素,我可以这样做:

someCollection.Any()

这优于

someCollection.Count() > 0

因为后者将计算集合中的所有项,所以当我不关心有多少项时,我只想知道是否有项。
有没有一个等价的方法来检查集合是否有多个项?类似于:

someCollection.Many()

而不是必须

someCollection.Count() > 1

我知道这是个愚蠢的问题,从我的研究来看,似乎没有。但由于这是我经常使用的东西,我想我应该向社区再核实一下。
谢谢

kb5ga3dv

kb5ga3dv1#

根据我的评论:
首先,应该检查IEnumerable<T> source * 实际上是IReadOnlyCollection<T>还是ICollection<T>,因为它有一个可以使用的.Count属性-这比任何迭代都更可取。
假设您的IEnumerable<T>没有O(1).Count属性,如果您想查看是否有 * 至少 * 1个元素(即“* 至少2个或更多 *”),则使用source.Take(2).Count() == 2source.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() ) )
{
    
}

相关问题