37

ちょっとLinqの専門家、

私は非常によく似た質問をしましたが、解決策はおそらく非常に簡単ですが、linqを使用してこの非常に単純なタスクを最も効率的に行う方法に頭を悩ませることはできません。

私の基本的なシナリオは、たとえば次のような値のリストがあることです。

Lst1:
a
a
b
b
c
b
a
c
a

そして、Lst1からのすべてのインデックスを保持する新しいリストを作成したいと思います。たとえば、value="a"です。したがって、この例では、次のようになります。

LstIndexes:
0
1
6
8

これで、ループを使用してこれを実行できることがわかり(Linqを優先して回避したい)、Linqを使用してこれを実行する方法を次のように理解しました。

LstIndexes= Lst1.Select(Function(item As String, index As Integer) index) _
                .Where(Function(index As Integer) Lst1(index) = "a").ToList

これに関する私の課題は、リストを2回繰り返すため、非効率的であるということです。

Linqを使用して最も効率的な方法で結果を取得するにはどうすればよいですか?

ありがとう!!!!

4

3 に答える 3

73

まず、コードは実際にはリストを2回反復するのではなく、1回だけ反復します。

そうは言っても、Select実際にはすべてのインデックスのシーケンスを取得しているだけです。それはより簡単にEnumerable.Range:で行うことができます

var result = Enumerable.Range(0, lst1.Count)
             .Where(i => lst1[i] == "a")
             .ToList();

リストが実際に2回繰り返されない理由を理解するには、ある程度慣れる必要があります。基本的な説明をしてみます。

SelectやWhereなどのほとんどのLINQメソッドをパイプラインとして考える必要があります。それぞれの方法は、少しの作業を行います。あなたがそれにメソッドを与える場合、Selectそれは本質的に「誰かが私の次のアイテムを私に尋ねるときはいつでも、私は最初に私の入力シーケンスにアイテムを尋ね、次に私がそれを何か他のものに変換しなければならないメソッドを使用します、そしてそれなら、私を使っている人にそのアイテムを渡してください。」 Where、多かれ少なかれ、「誰かが私にアイテムを要求するときはいつでも、私はアイテムの入力シーケンスを要求します。関数がそれが良いと言うなら、私はそれを渡します。そうでなければ、私はアイテムを要求し続けます。合格したものを手に入れました。」

したがって、それらをチェーンするToListと、最初のアイテムを要求すると、最初のアイテムとしてに移動Whereし、最初のアイテムにWhere移動しSelectて要求Selectし、リストに移動して最初のアイテムを要求します。次に、リストに最初の項目が表示されます。 Select次に、そのアイテムを吐き出す必要のあるもの(この場合はint 0のみ)に変換し、に渡しますWhere。 そのアイテムを受け取り、それが真であると判断する関数を実行して、Whereに吐き出し、リストに追加します。その後、そのすべてがさらに9回発生します。これは、リストから各アイテムを1回だけ要求することになり、各結果を直接にフィードすることを意味します。0ToListSelectWhere、「テストに合格」した結果を直接ToListにフィードし、ToListがリストに保存します。すべてのLINQメソッドは、ソースシーケンスを1回だけ繰り返すように注意深く設計されています(1回繰り返される場合)。

これは最初は複雑に思えますが、実際にはコンピュータがこれらすべてを実行するのは非常に簡単であることに注意してください。実際には、最初に思われるほどパフォーマンスを重視するものではありません。

于 2012-10-24T18:31:35.903 に答える
7

これは機能しますが、間違いなくそれほどきれいではありません。

var result = list1.Select((x, i) => new {x, i})
                  .Where(x => x.x == "a")
                  .Select(x => x.i);
于 2012-10-24T19:14:30.273 に答える
1

これはどうですか、それは私にとってはかなりうまくいきます。

   static void Main(string[] args)
    {
        List<char> Lst1 = new List<char>();
        Lst1.Add('a'); 
        Lst1.Add('a');   
        Lst1.Add('b');   
        Lst1.Add('b');   
        Lst1.Add('c');   
        Lst1.Add('b');   
        Lst1.Add('a');   
        Lst1.Add('c');
        Lst1.Add('a');

        var result = Lst1.Select((c, i) => new { character = c, index = i })
                         .Where(list => list.character == 'a')
                         .ToList();
    }
于 2012-10-24T18:47:15.853 に答える