2017-03-26 46 views
0

我想批IEnumerable<T>相等的子集和整個以下解決方案來:IEnumerable的配料差異

  1. MoreLinq的NuGet庫批量,它的實現在這裏詳細描述:

    MoreLinq - Batch ,粘貼下面的源代碼:

    public static IEnumerable<TResult> Batch<TSource, TResult>(this 
        IEnumerable<TSource> source, int size, 
         Func<IEnumerable<TSource>, TResult> resultSelector) 
    { 
        if (source == null) throw new ArgumentNullException(nameof(source)); 
        if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size)); 
        if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); 
         return BatchImpl(source, size, resultSelector); 
    } 
    
    private static IEnumerable<TResult> BatchImpl<TSource, TResult> (this IEnumerable<TSource> source, int  
          size,Func<IEnumerable<TSource>, TResult> resultSelector) 
    { 
        Debug.Assert(source != null); 
        Debug.Assert(size > 0); 
        Debug.Assert(resultSelector != null); 
    
        TSource[] bucket = null; 
        var count = 0; 
    
    foreach (var item in source) 
    { 
        if (bucket == null) 
        { 
         bucket = new TSource[size]; 
        } 
    
        bucket[count++] = item; 
    
        // The bucket is fully buffered before it's yielded 
        if (count != size) 
        { 
         continue; 
        } 
    
        // Select is necessary so bucket contents are streamed too 
        yield return resultSelector(bucket); 
    
        bucket = null; 
        count = 0; 
    } 
    
    // Return the last bucket with all remaining elements 
    if (bucket != null && count > 0) 
    { 
        Array.Resize(ref bucket, count); 
         yield return resultSelector(bucket); 
    } 
    } 
    
  2. 另一個最佳解決方案可用於以下l油墨(更高效的存儲器):

    IEnumerable Batching,下方粘貼源代碼:

    public static class BatchLinq 
    { 
        public static IEnumerable<IEnumerable<T>> CustomBatch<T>(this IEnumerable<T> source, int size) 
        { 
         if (size <= 0) 
         throw new ArgumentOutOfRangeException("size", "Must be greater than zero."); 
    
        using (IEnumerator<T> enumerator = source.GetEnumerator()) 
         while (enumerator.MoveNext()) 
          yield return TakeIEnumerator(enumerator, size); 
        } 
    
        private static IEnumerable<T> TakeIEnumerator<T>(IEnumerator<T> source, int size) 
        { 
         int i = 0; 
         do 
          yield return source.Current; 
         while (++i < size && source.MoveNext()); 
        } 
    } 
    

兩種溶液提供最終結果作爲IEnumerable<IEnumerable<T>>

我發現在下面的代碼段的差異:從任一方法

var result = Fetch IEnumerable<IEnumerable<T>>上述

result.Count()建議的,導致不同的結果,其校正MoreLinq批次,但不正確的其它一個,甚至當結果是正確的,同爲兩個

考慮follwing例如:

IEnumerable<int> arr = new int[10] {1,2,3,4,5,6,7,8,9,10}; 

For a Partition size 3 

arr.Batch(3).Count(), will provide result 4 which is correct 

arr.BatchLinq(3).Count(), will provide result 10 which is incorrect 

即使提供的批處理結果是正確的,當我們做ToList()時,仍然是錯誤,因爲我們仍在處理第二種方法中的內存流,並且未分配內存,但仍不正確的結果不應該如此,任何視圖/建議

+1

我認爲你需要分享你正在執行的代碼。 – buffjape

+0

如果你的問題仔細看,代碼是在那裏,直到除非你喜歡複製從相應的鏈接的源代碼了。 你認爲什麼部分缺失/不清楚,兩個批處理機制都是IEnumerable擴展 –

+0

@Veverke沒有批處理工作,這是有趣的部分,因爲我提到它顯示正確的結果做'ToList()',但是Count( )'不正確。也是不正確的代碼是堆棧溢出問題的答案,不涉及MoreLinq,我這個問題的答案比較喜歡,因爲它的優化,但 –

回答

1

之所以第二個結果返回計數= 10是因爲它使用while (enumerator.MoveNext())這將產生10倍,並導致產生枚舉含有10個可枚舉,而不是3

回答與提供合理的得分較高https://stackoverflow.com/a/13731854/2138959中引用的問題解決問題的方法也是如此。

+0

正如在引用的答案指出,它不是理想的,因爲它擊敗了延遲評估到期到GroupBy –

+0

是的,那是真的。 –