37

嘿,那里的 Linq 专家,

我刚刚问了一个非常相似的问题,并且知道解决方案可能非常简单,但仍然发现自己无法理解如何使用 linq 以最有效的方式完成这个相当简单的任务。

我的基本情况是我有一个值列表,例如,说:

Lst1:
a
a
b
b
c
b
a
c
a

我想创建一个新列表,它将保存 Lst1 中的所有索引,例如 value = "a"。所以,在这个例子中,我们会有:

LstIndexes:
0
1
6
8

现在,我知道我可以使用 Loops 来做到这一点(我宁愿避免使用 Linq),我什至想出了如何通过以下方式使用 Linq 来做到这一点:

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

我对此的挑战是它迭代列表两次,因此效率低下。

如何使用 Linq 以最有效的方式获得结果?

谢谢!!!!

4

3 回答 3

73

首先,您的代码实际上并没有迭代列表两次,它只迭代一次。

也就是说,您Select实际上只是获得了所有索引的序列;这更容易完成Enumerable.Range

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

理解为什么列表实际上没有迭代两次需要一些时间来适应。我将尝试给出一个基本的解释。

您应该将大多数 LINQ 方法(例如 Select 和 Where)视为管道。每种方法都做了一些微小的工作。在Select你给它一个方法的情况下,它基本上说,“每当有人问我下一个项目时,我会首先向我的输入序列询问一个项目,然后使用我必须将其转换为其他东西的方法,并且然后把那个东西交给任何使用我的人。” Where,或多或少是在说,“每当有人向我要一个项目时,我都会向我的输入序列询问一个项目,如果函数说它很好,我会传递它,如果不是,我会一直要求项目直到我得到一个通过的。”

因此,当您将它们链接起来时,发生的情况是ToList要求第一项,然后转到Whereto 作为它的第一项,Where转到Select并要求它的第一项,Select转到列表以要求它的第一项。然后列表提供它的第一项。 Select然后将该项目转换为它需要吐出的内容(在这种情况下,只是 int 0)并将其提供给Where. Where获取该项目并运行它的函数,该函数确定它是真的,因此吐出0ToList,它将它添加到列表中。然后整个事情又发生了9次。这意味着Select最终将只要求列表中的每个项目一次,并将其每个结果直接提供给Where,它将“通过测试”的结果直接提供给 ToList,后者将它们存储在一个列表中。所有 LINQ 方法都经过精心设计,只对源序列进行一次迭代(当它们被迭代一次时)。

请注意,虽然这对您来说一开始看起来很复杂,但计算机实际上很容易完成所有这些工作。它实际上并不像最初看起来那样密集。

于 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 回答