1

次の例でLINQに切り替えるのに苦労しています。

int[] inputs = { 5, 3, 5, 66, 4, 5 };
int[] indexes; // I want to have the indexes of '5's in 
               // the inputs array, which is { 0, 2, 5 }

// My way (traditional for loop)

List<int> indexesList = new List<int>();
for (int i = 0; i < inputs.Length; i++)
    if (inputs[i] == 5)
        indexesList.Add(i);

indexes = indexesList.ToArray();

// LINQ way

var indexes = inputs.Select((s, i) => new { i, s })
                    .Where(t => t.s == 5)
                    .Select(t => t.i).ToArray();

質問1.効率(速度、メモリ使用量)の観点から、コードをLINQに変換すると、何か利点がありますか?

質問2.本当の場合、LINQでそれを行うためのよりエレガントな方法はありますか?

PS:このメソッドは、私の実際のプロジェクトでは非常に頻繁に呼び出されることに注意してください。したがって、速度やメモリ使用量を少し改善すると、プロセス全体が大幅に向上します。

4

4 に答える 4

2

LINQコードを使用する場合、パフォーマンス上の利点はありません。これは、それを読むだけで明らかです。各値をそのインデックスに関連付けるために、新しいオブジェクトが作成されます。

(s, i) => new { i, s }

これらの匿名オブジェクトは、インデックスと値を結び付けるための容器である以外の目的はありません。したがって、関連するすべてのメモリ管理は、カウンターをまっすぐに維持するのと比較して、純粋なオーバーヘッドです。

LINQは、ほとんどの場合、メカニズムではなく意図を強調しているため、読みやすさの利点があると言う人もいるかもしれませんが、この特定のケースでは、それがプロサックソリューションよりも優れているとは思いません。

于 2012-11-26T19:56:18.427 に答える
1

最初に構造をタプルのコレクションに変換してからインデックスを選択するため、linqの方法は実際には効率が悪いと言えます。

より優雅に見えるかもしれませんが、そこで何が起こっているのかを正確に理解するのは少し難しいとも言えます。

個人的にはイテレーションをお勧めします。


本当に効率を上げる必要がある場合は、実用的であれば、入力を並べ替えることをお勧めします。初めて並べ替えるときは時間がかかりますが、同じリストを複数回検索すると、費用がかかります。

于 2012-11-26T19:57:09.767 に答える
1

LINQの方法で実行したい場合は、述語に一致する要素のインデックスを返すための独自の拡張メソッドを実装することをお勧めします。

public static IEnumerable<int> IndexesWhere<TSource>(
    this IEnumerable<TSource> source, 
    Func<TSource, bool> predicate)
{
    int i = 0;

    foreach (TSource element in source)
    {
        if (predicate(element))
            yield return i;

        i++;
    }
}

その後、次のように呼び出すことができます。

var indexes = inputs.IndexesWhere(s => s == 5);

このアプローチを使用する利点は次のとおりです。

  1. Select((s, i) => new { i, s })(アプローチとは異なり)匿名タイプのインスタンスを作成することは避けてください。
  2. シーケンスはオンデマンドで列挙できます。つまり、のようなことをしたいだけの場合は、インデックスの完全な配列を入力するよりも効率的ですindexes.Take(2)
于 2012-11-26T19:59:04.443 に答える
1

LINQを使用して、匿名オブジェクトの作成を回避する方法は次のとおりです。

var indexes = Enumerable.Range(0, inputs.Length)
                        .Where(x => inputs[x] == 5)
                        .ToArray();

そのパフォーマンスはおそらくforループを使用する場合と似ていますが、確実にテストする必要があります。

于 2012-11-26T20:15:00.160 に答える