Skip + Take = Substring になる?

System.Linq.Enumerable のメソッドをいくつか紹介します。
利用場面はあまり思いつきませんが、例えば2番目と3番目の要素にアクセスするコードは、以下のように書くことができます。

using System;
using System.Linq;

public static class ConsoleApplication1
{
    public static void Main()
    {
        var a = new int[] { 1, 2, 3, 4, 5 };
        foreach (var t in a.Skip(1).Take(2))
        {
            Console.WriteLine(t);
        }
    }
}

実行結果:

2
3

少し無理気味ですが、string に対して同様のことを行うことで、
string.Substring() の代わりにならないか、と考えてみました。

using System;
using System.Linq;
using System.Collections.Generic;

public static class ConsoleApplication1
{
    public static void Main()
    {
        string s = "12345";
        // s.Substring(1, 2) と同じ
        Console.WriteLine(s.Skip(1).Take(2).ToStr());
    }

    public static string ToStr(this IEnumerable s)
    {
        return new string(s.ToArray());
    }
}

実行結果:

23

私は、「string.Substring() の第1引数が、0オリジンで開始位置を指定する」
ということをよく忘れるのですが、(忘れるな、という話もある)
Skip(1).Take(2) のように書ければ、「1つスキップして2つ取る」と素直に読め、
意味を間違えることがないかと思います。

ただ、ToString() と書けないのが残念な点と、性能の問題があります。

s.Skip(1).Take(2).ToStr() を 10M回実行: 2,537msec
s.Substring(1, 2) を 10M回実行: 177msec

圧倒的な性能差が出ました。

return new string(s.ToArray());

の部分を

return string.Concat(s.ToArray());

と書き換えると、3,598msec とさらに悪くなり、

var sb = new System.Text.StringBuilder();
foreach (var c in s)
{
    sb.Append(c);
}
return sb.ToString();

としてみても、1,790msec と改善はされるものの string.Substring() には
はるか及びませんでした。

以上です。

おすすめ

TOP
TOP