1. peace2048

    Posted

    peace2048
Changes in title
+T型のシーケンスを、任意サイズの配列のシーケンスに変える
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,70 @@
+タイトルから内容が分かりにくいですが、次のようなことをします。
+
+```vbnet
+For Each a In Enumerable.Range(1, 10).Buffer(5)
+ For Each b In a
+ Console.Write("{0} ", b)
+ Next
+ Console.WriteLine()
+Next
+```
+
+を実行すると
+
+> 1 2 3 4 5
+> 6 7 8 9 10
+
+と表示されます。で、タイトルの内容を処理するのが `Buffer()` です。
+IEnumerable(Of T) に拡張メソッドを追加しています。
+ソースコードを次に示します。
+
+```vbnet:Buffer.vb
+
+Module EnumerableExBuffer
+
+ <Extension>
+ Public Function Buffer(Of T)(
+ ByVal source As IEnumerable(Of T),
+ ByVal count As Integer
+ ) As IEnumerable(Of T())
+
+ If source Is Nothing Then Throw New ArgumentNullException("source")
+ If count < 1 Then Throw New ArgumentOutOfRangeException("count")
+
+ Return Buffer_(source, count)
+ End Function
+
+ Private Iterator Function Buffer_(Of T)(
+ ByVal source As IEnumerable(Of T),
+ ByVal count As Integer
+ ) As IEnumerable(Of T())
+
+ Dim list = New List(Of T)(count)
+ For Each item In source
+ list.Add(item)
+ If list.Count = count Then
+ Yield list.ToArray()
+ list.Clear()
+ End If
+ Next
+ If list.Count > 0 Then
+ Yield list.ToArray()
+ End If
+ End Function
+
+End Module
+
+```
+
+実際にはどんな使い方があるかというと、一例で、文字列"414243444546"を"ABCDEF"に変換するときに
+
+```vbnet
+Dim s = Encoding.ASCII.GetString(
+ "414243444546"
+ .Buffer(2)
+ .Select(Function(a) New String(a))
+ .Select(Function(a) Convert.ToByte(a, 16))
+ .ToArray())
+```
+
+と書ける。文字列は `IEnumerable(Of Char)` に変換できるので、`.Buffer(2)` で 2文字の配列のシーケンスにします。その後、Char の配列から文字列を作成し、Convert.ToByte で16進文字列をバイトに変換し、最後にバイト配列にしています。作成されたバイト配列を ASCII でデコードすれば目的の文字列が得られます。