0

我想计算 IEnumerable 列表中元素的等级并将其分配给成员。但下面的代码仅在第一次调用时才有效。第二次调用从最后一个排名值开始。所以我得到的是 012 和 345 而不是输出 012 和 012

    class MyClass
    {
        public string Name { get; set; }
        public int Rank { get; set; }
    }

    public void SecondTimeRankEvaluvate()
    {
        MyClass[] myArray = new MyClass[] 
        {
            new MyClass() { Name = "Foo" },
            new MyClass() { Name = "Bar" },
            new MyClass() { Name = "Baz" }
        };

        int r = 0;
        var first = myArray.Select(s => { s.Rank = r++; return s; });

        foreach (var item in first)
        {
            Console.Write(item.Rank);
        }
        // Prints 012
        Console.WriteLine("");
        foreach (var item in first)
        {
            Console.Write(item.Rank);
        }
        // Prints 345
    }

我知道该变量r在第二次调用时被捕获(关闭)并重用。我不想要那种行为。有什么干净的方法来计算排名并分配它吗?变量(在r实际代码中)也不在foreach存在循环的同一范围内。它在一个返回的函数中var first

4

3 回答 3

6
var first = myArray.Select((s, i) => { s.Rank = i; return s; });
于 2012-04-28T13:50:51.170 回答
3

LINQ 使用惰性求值并在Select您每次使用myArray.

您可以通过将结果存储在List.

改变

var first = myArray.Select(s => { s.Rank = r++; return s; });

var first = myArray.Select(s => { s.Rank = r++; return s; }).ToList();

myArray另一种方法是使用Zip每次加入一个新序列,像这样

var first = myArray.Zip(Enumerable.Range(0, int.MaxValue), (s, r) =>
{
    s.Rank = r;
    return s;
});
于 2012-04-28T13:46:12.830 回答
1

如果您不查询集合,则不应使用 LINQ。

要更新数组中的每个项目,请使用for循环:

for (int i = 0; i < myArray.Length; i++)
{
    myArray[i].Rank = i;
}

要更新可枚举中的每个项目,请使用foreach循环:

int r = 0;
foreach (var item in myArray)
{
    item.Rank = r++;
}
于 2012-04-28T13:47:38.670 回答