2011/08/25

C#練習がてらslices

C#の拡張メソッドでgaucheのutil.listにあるslicesっぽいもの書いてみた。組み込みでこういうのあるのかも知らんけども。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System.Linq
{
public static class EnumerableEx
{
public static void ForEach<T>(this IEnumerable<T> value, Action<T> action)
{
foreach (var v in value) action(v);
}
public static IEnumerable<T[]> Slices<T>(this IEnumerable<T> col, int k)
{
return Slices<T, T[]>(col, k, t => t.ToArray());
}
public static IEnumerable<TResult> Slices<TSource, TResult>
(this IEnumerable<TSource> col, int k, Func<IEnumerable<TSource>, TResult> resultSelector)
{
List<TResult> ret = new List<TResult>();
for (int i = 0; i < col.Count(); i = i + k)
{
ret.Add(resultSelector(col.Skip<TSource>(i).Take<TSource>(k)));
}
return ret;
}
}
}
namespace test
{
class Program
{
static void Main(string[] args)
{
Enumerable.Range(0, 100).Slices(3).ForEach(n =>
{
n.ForEach(i => Console.Write("{0} ", i));
Console.WriteLine();
});
Console.WriteLine();
Enumerable.Range(0, 100)
.Slices<int, int>(5, e => e.Sum())
.ForEach(i => Console.Write("{0} ", i));
Console.WriteLine();
Enumerable.Range(0, 100)
.Slices(2)
.Select<int[], string>(nums => Convert.ToString(int.Parse(nums.Aggregate<int, string>(
string.Empty,
(a, i) => a + i.ToString())), 16))
.ForEach(s => Console.Write("{0} ", s.ToUpper()));
Console.ReadLine();
}
}
}
view raw slices.cs hosted with ❤ by GitHub
出力
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
15 16 17
18 19 20
21 22 23
24 25 26
27 28 29
30 31 32
33 34 35
36 37 38
39 40 41
42 43 44
45 46 47
48 49 50
51 52 53
54 55 56
57 58 59
60 61 62
63 64 65
66 67 68
69 70 71
72 73 74
75 76 77
78 79 80
81 82 83
84 85 86
87 88 89
90 91 92
93 94 95
96 97 98
99
10 35 60 85 110 135 160 185 210 235 260 285 310 335 360 385 410 435 460 485
1 17 2D 43 59 3F3 4BD 587 651 71B 7E5 8AF 979 A43 B0D BD7 CA1 D6B E35 EFF FC9 1093 115D 1227 12F1 13BB 1485 154F 1619 16E3 17AD 1877 1941 1A0B 1AD5 1B9F 1C69 1D33 1DFD 1EC7 1F91 205B 2125 21EF 22B9 2383 244D 2517 25E1 26AB
view raw output hosted with ❤ by GitHub
Achiralというのをちらっと眺めてみたけど、Schemeで見慣れたようなものもあれば何をしているのかわからないものまでいろいろ。
拡張メソッドいいれすれー。  マクロもあればいいのに。Lispの伝統的なマクロをC系シンタックスでってのは無理があるのかもしれないけど、Pure言語にあるようなマクロだったらいけるんじゃないの。

追記

職場で「これだと遅延評価が効かないんで、こうしたら良いよー。」と教えてもらったので、それを参考に書き直してみました。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace System.Linq
{
public static class EnumerableEx
{
public static IEnumerable<T[]> Slices<T>(this IEnumerable<T> col, int k)
{
return Slices<T, T[]>(col, k, t => t.ToArray());
}
public static IEnumerable<TResult> Slices<TSource, TResult>
(this IEnumerable<TSource> col, int k, Func<IEnumerable<TSource>, TResult> resultSelector)
{
List<TSource> result = new List<TSource>(k);
foreach (var v in col)
{
result.Add(v);
if (result.Count() == k) {
yield return resultSelector(result);
result.Clear();
}
}
if (0 < result.Count) {
yield return resultSelector(result);
}
}
public static void ForEach<T>(this IEnumerable<T> value, Action<T> action)
{
foreach (var v in value) action(v);
}
}
}
view raw Slices2.cs hosted with ❤ by GitHub




0 件のコメント:

コメントを投稿