読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

Linq入門記-63 (シーケンスを特定の数のチャンクに分割する方法, Chunk, 拡張メソッド, yield return, Any, Take, Skip)


stackoverflowにLinqを使って、特定のシーケンスを決まった数のチャンクに分割する
コードがあったので、メモメモ。要素が多いシーケンスを相手にするときに便利です。


以下、サンプルです。

  #region LinqSamples-59
  /// <summary>
  /// Linqにて、シーケンスをチャンクに分割して処理するサンプルです.
  /// </summary>
  public class LinqSamples59 : IExecutable
  {
    public void Execute()
    {
      //
      // 要素が10のシーケンスを2つずつのチャンクに分割.
      //
      foreach (var chunk in Enumerable.Range(1, 10).Chunk(2))
      {
        Console.WriteLine("Chunk:");
        foreach (var item in chunk)
        {
          Console.WriteLine("\t--> {0}", item);
        }
      }
      
      //
      // 要素が10000のシーケンスを1000ずつのチャンクに分割し
      // それぞれのチャンクごとにインデックスを付与.
      //
      foreach (var chunk in Enumerable.Range(1, 10000).Chunk(1000).Select((x, i) => new { Index = i, Count = x.Count() }))
      {
        Console.WriteLine(chunk);
      }
    }
  }
  
  public static class LinqSamples59_Extensions
  {
    /// <summary>
    /// シーケンスを指定されたサイズのチャンクに分割します.
    /// </summary>
    public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> self, int chunkSize)
    {
      if (chunkSize <= 0)
      {
        throw new ArgumentException("Chunk size must be greater than 0.", "chunkSize");
      }
      
      while (self.Any())
      {
        yield return self.Take(chunkSize);
        self = self.Skip(chunkSize);
      }
    }
  }
  #endregion

実行すると以下のようになります。

  Chunk:
  	--> 1
  	--> 2
  Chunk:
  	--> 3
  	--> 4
  Chunk:
  	--> 5
  	--> 6
  Chunk:
  	--> 7
  	--> 8
  Chunk:
  	--> 9
  	--> 10
  { Index = 0, Count = 1000 }
  { Index = 1, Count = 1000 }
  { Index = 2, Count = 1000 }
  { Index = 3, Count = 1000 }
  { Index = 4, Count = 1000 }
  { Index = 5, Count = 1000 }
  { Index = 6, Count = 1000 }
  { Index = 7, Count = 1000 }
  { Index = 8, Count = 1000 }
  { Index = 9, Count = 1000 }


Any, Take, Skipは以前の記事にて記述していますので
よければ、ご参照ください。

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。