簡體   English   中英

當集合有多個項目時,等效於 Linq 的 Any() function

[英]Equivalent of Linq's Any() function for when a collection has multiple items

在 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() == 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() ) )
{
    
}
  • 是的,它很丑……很不幸, 但是 C# 仍然不支持這種級別的泛型類型推斷——也不支持部分泛型參數應用
  • list.GetEnumerator()部分是必需的,因為它是將基於struct的枚舉器傳遞到通用代碼中而無需裝箱(至少,不是沒有反射)的唯一方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM