如何计算 IEnumerable并将其存储在 T 类型中

本文关键字:存储 类型 的秩 计算 IEnumerable 何计算 | 更新日期: 2023-09-27 18:32:37

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

    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<</p>

如何计算 IEnumerable<T 的秩>并将其存储在 T 类型中

div class="answers"的函数中>
var first = myArray.Select((s, i) => { s.Rank = i; return s; });

LINQ 使用惰性求值,并在每次使用 myArray 时运行 Select 部分。

通过将结果存储在 List 中,可以强制仅执行一次评估。

改变

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

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

另一种方法是每次都使用 ZipmyArray与新序列连接起来,如下所示

var first = myArray.Zip(Enumerable.Range(0, int.MaxValue), (s, r) =>
{
    s.Rank = r;
    return s;
});

如果不查询集合,则不应使用 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++;
}