【问题标题】:How to compute rank of IEnumerable<T> and store it in type T如何计算 IEnumerable<T> 的等级并将其存储在类型 T 中
【发布时间】:2012-04-28 13:41:45
【问题描述】:

我想计算 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

的函数中

【问题讨论】:

    标签: c# closures captured-variable


    【解决方案1】:
    var first = myArray.Select((s, i) => { s.Rank = i; return s; });
    

    【讨论】:

    • 这是Select的重载。
    【解决方案2】:

    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;
    });
    

    【讨论】:

    • 谢谢。是的,这会奏效。但是有没有什么干净的方法可以动态生成延迟执行和排名,而不是将整个事情转换为列表。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2014-07-20
      • 2015-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 2022-08-19
      相关资源
      最近更新 更多