ちょっとLinqの専門家は、
私は非常に似た質問をして、解決策はおそらく非常に簡単だと知っていますが、linqを使用して最も効率的な方法でこの非常に簡単なタスクをどのように行うかについて頭を悩ませることができません。
私の基本的なシナリオは、次のような値のリストがあることです。
Lst1:
a
a
b
b
c
b
a
c
a
そして、たとえば、値= "a"であるLst1のすべてのインデックスを保持する新しいリストを作成します。したがって、この例では次のようになります。
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を使用して最も効率的な方法で結果を取得するにはどうすればよいですか?
ありがとう!!!!
まず、コードは実際にリストを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
はそのアイテムを受け取り、それが真であると判断する関数を実行します。したがって、0
をToList
に追加すると、リストに追加されます。その後、そのすべてがさらに9回発生します。これは、Select
がリストから各項目を1回だけ要求することを意味し、各結果をWhere
に直接フィードします。これにより、「テストに合格」した結果がToListに直接送られ、リストに保存されます。すべてのLINQメソッドは、ソースシーケンスを1回のみ(1回反復する場合)反復するように慎重に設計されています。
これは最初は複雑に思えますが、実際にはコンピューターがこれをすべて簡単に実行できることに注意してください。実際には、最初に思えるかもしれないほどパフォーマンスが集中しているわけではありません。
これは機能しますが、間違いなく適切ではありません。
var result = list1.Select((x, i) => new {x, i})
.Where(x => x.x == "a")
.Select(x => x.i);
これはどうですか、私にとってはかなりうまくいきます。
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();
}