7

最初の IEnumerable 項目を、反復ごとにテストすることなく、他の項目とは異なる方法で処理する最もエレガントな方法は何でしょうか?

各反復でテストすると、次のようになります。

// "first item done" flag
bool firstDone = false;

// items is an IEnumerable<something>
foreach (var item in items)
{
    if (!firstDone)
    {
        // do this only once
        ProcessDifferently(item);
        firstDone = true;
        continue;
    }

    ProcessNormally(item);
}

私がこれを行う場合:

ProcessDifferently(items.First());
ProcessNormally(items.Skip(1)); // this calls `items.GetEnumerator` again

それはGetEnumerator2回呼び出されますが、これは避けたいと思います(たとえば、Linq-to-Sqlの場合)。

コードを何度も実行する必要がある場合、どのようにしますか?

4

3 に答える 3

12

複数の場所でそれを行う必要がある場合は、メソッドを抽出します。

public void Process<T>(IEnumerable<T> source,
                       Action<T> firstAction,
                       Action<T> remainderAction)
{
    // TODO: Argument validation
    using (var iterator = source.GetEnumerator())
    {
        if (iterator.MoveNext())
        {
            firstAction(iterator.Current);
        }
        while (iterator.MoveNext())
        {
            remainderAction(iterator.Current);
        }
    }
}

と呼ばれる:

Process(items, ProcessDifferently, ProcessNormally);

他のオプションもありますが、それは実際には状況によって異なります。

于 2011-07-01T16:48:07.747 に答える
1

別の方法は次のとおりです。

    private static void Main(string[] args)
    {
        var testdata = new[] { "a", "b", "c", "d", "e" };

        var action = FirstThenRest<string>(
            s => Console.WriteLine("First: " + s),
            s => Console.WriteLine("Rest: " + s));

        foreach (var s in testdata)
            action(s);
    }

    public static Action<T> FirstThenRest<T>(Action<T> first, Action<T> rest)
    {
        Action<T> closure = t =>
                            {
                                first(t);
                                closure = rest;
                            };

        return t => closure(t);
    }

これは以下を出力します:

First: a
Rest: b
Rest: c
Rest: d
Rest: e

条件なし。:D

編集:「頭」と「尾」はおそらくより良い用語ですが、私は怠惰すぎて今それを変更することはできません.

于 2011-07-01T17:31:50.853 に答える
0

昔ながらの方法でそれを行うことができます:

var itemsList = items.ToList();
ProcessDifferently(itemsList[0]);

for(int i=1;i<itemsList.Count;i++)
{
   ProcessNormally(itemsList[i]);
}
于 2011-07-01T16:54:09.110 に答える