簡體   English   中英

從對象集合創建批次

[英]Create Batches from Object collection

我有一個對象集合(計數超過500個),我想用某種邏輯對其進行批處理,例如一批50個,我應該得到10套。(10 * 50 = 500)

我正在使用以下邏輯:

 public class CustomEngineReader :IEnumerable<List<EngineToken>>
{
    StreamReader sr;
    int _batchSize = 1;

    public CustomFileReader(List<EngineToken> tokens, int batchSize)
    {
        if (batchSize > 0)
        {
            _batchSize = batchSize;
        }



    }


    public IEnumerator<List<string>> GetEnumerator()
    {

        string input = string.Empty;

        foreach(var item in EngineTokens)
        {
            int i = 0;
            List<string> batch = new List<string>();

            while (i < _batchSize && item !=null)
            {
                batch.Add(item );
                i++;
            }

            if (batch.Count != 0)
            {
                yield return batch;
            }
        }

    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

我正在使用上面的代碼如下

CustomEngineReader reader = new CustomEngineReader (this.tokencollection, 50);
foreach(List<EngineToken> items in reader)
{
       //in each iteration we get batch specified objects
       foreach(EngineToken item in items)
       {
          //Process
       }    
}

沒用

foreach內部有一個while循環意味着您要一遍又一遍地添加相同的項目,直到達到批量大小為止。

您還需要在foreach之外創建batch對象,以便可以將循環中的多個項目添加到其中。

就個人而言,我更喜歡將其編寫為擴展方法,而不是單獨的類,以遵循LINQ編程風格。 也可以將其微不足道地泛化,從而大大提高其實用性。 我對Batch實現是:

public static IEnumerable<IEnumerable<T>> Batch<T>(
    this IEnumerable<T> source, int batchSize)
{
    List<T> buffer = new List<T>(batchSize);

    foreach (T item in source)
    {
        buffer.Add(item);

        if (buffer.Count >= batchSize)
        {
            yield return buffer;
            buffer = new List<T>(batchSize);
        }
    }
    if (buffer.Count > 0)
    {
        yield return buffer;
    }
}

您正在循環中多次添加同一項目。 嘗試:

public IEnumerator<List<EngineToken>> GetEnumerator()
{

    string input = string.Empty;

    int i=0;
    List<string> batch = new List<string>();
    foreach(var item in EngineTokens)
    {
        batch.Add(item);
        i++;
        if(i==_batchSize)
        {
             yield return batch;
             batch = new List<string>();
             i = 0;
        }
    }
    if (batch.Count != 0)
    {
        yield return batch;
    }

}

這是一個更簡單的實現,非線程安全。 為了線程安全,您需要根據需要添加鎖。

public IEnumerator<List<EngineToken> GetEnumerator()
{    
        var currentBatch = EngineTokens.Take(_batchSize);
        EngineTokens = EngineTokens.Skip(_batchSize).ToList();
        return currentBatch;

}

暫無
暫無

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

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