编写lambda表达式以对列表执行计算

时间:2011-09-04 07:07:10

标签: c# lambda

我有一个List / IEnumerable对象,我想对其中一些进行计算。

e.g。 myList.Where(F => f.Calculate == TRUE).Calculate();

根据Where子句更新myList,以便执行所需的calulcation并根据需要更新整个列表。

该列表包含“行”,其中金额在Month1,Month2,Month3 ... Month12,Year1,Year2,Year3-5或“Long Term”中 大多数行是固定的,并且总是属于这些月中的一个,但是一些“行”根据其“成熟日期”进行了计算。

哦,只是让事情复杂化!列表(目前)是来自几个linq查询的匿名类型。如果需要,我可以把它变成一个具体的课程,但如果我能避免的话,我宁愿不这样做。

所以,我想调用一种仅适用于计算行的方法,并将正确的数量放入正确的“月份”。 我并不担心计算逻辑,而是如何将它变成一个易于阅读的方法来更新列表,而不是理想情况下返回一个新列表。

[是否有可能写一个lambda扩展方法来进行计算和where - 或者这种矫枉过正是因为Where()已经存在?]

3 个答案:

答案 0 :(得分:5)

就个人而言,如果你想要更新列表 ,我只会使用一个简单的循环。遵循和维护将更加简单:

for (int i=0;i<list.Count;++i)
{
     if (list[i].ShouldCalculate)
         list[i] = list[i].Calculate();
}

这至少会更加明显,它会更新。 LINQ期望执行查询,而不是改变数据。


如果你真的想为此使用LINQ,你可以 - 但如果你想要List<T>作为你的结果,它仍然需要一份副本:

myList = myList.Select(f => f.ShouldCalculate ? f.Calculate() : f).ToList();

这会根据需要调用您的Calculate()方法,并在不需要时复制原始文件。但它确实需要一个副本来创建一个新的List<T>,正如您所提到的那样(在评论中)。

但是,我个人的偏好仍然是在这种情况下使用循环。我发现意图更加明确 - 另外,你避免了不必要的复制操作。


编辑#2:

鉴于此评论:

  

哦,只是让事情复杂化!列表(目前)是来自几个linq查询的匿名类型

如果您真的想使用LINQ样式语法,我建议您不要在原始查询上调用ToList()。如果您使用原始IEnumerable<T>形式保留它们,则可以轻松地执行上面的第二个选项,但是在原始查询中:

var myList = query.Select(f => f.ShouldCalculate ? f.Calculate() : f).ToList();

这样做的好处是只能构建一次列表并阻止复制,因为在此操作之前不会对原始序列进行评估。

答案 1 :(得分:2)

LINQ主要是针对无副作用的查询,而匿名类型本身是不可变的(尽管它们当然可以维护对可变类型的引用)。

鉴于你想要改变列表,LINQ不太适合。

根据Reed的建议,我会使用直接for循环。但是,如果要在不同点执行不同的计算,可以将其封装起来:

public static void Recalculate<T>(IList<T> list,
                                  Func<T, bool> shouldCalculate,
                                  Func<T, T> calculation)
{
    for (int i = 0; i < list.Count; i++)
    {
        if (shouldCalculate(items[i]))
        {
            items[i] = calculation(items[i]);
        }
    }
}

如果真的希望以流畅的方式使用它,你可以让它返回列表 - 但我个人会反对,因为它会看起来就像LINQ一样没有副作用。

和里德一样,我更愿意通过创建新序列来实现这一目标...

答案 2 :(得分:0)

Select不会复制或克隆它传递给传递的委托的对象,对该对象的任何状态更改都将通过容器中的引用进行反映(除非它是值类型)。

因此更新参考类型不是问题。

要替换对象(或使用值类型 1 时),这更复杂,并且没有内置的LINQ解决方案。 for循环最清晰(与其他答案一样)。


1 当然,请记住mutable value types are evil