2

这个问题有点难以解释,但我会尽量简短。

我有一种情况,我有一组键/值对,例如这个。

class Foo {
   int Number { get; set; }
   int Value { get; set; }
}

所以我会像这样设置一个集合......

var collection = new List<Foo>{
   new Foo { Number = 1, Value = 1 },
   new Foo { Number = 2, Value = 2 },
   new Foo { Number = 3, Value = 3 },
   new Foo { Number = 4, Value = 4 }
};

所以我希望基本上能够找到所有先前值的总和小于或等于给定值的数字。例如 ...

如果给定值 3,则返回的 Number 应该是collection[1]。(collection[0]值为 1,collection[1]值为 2,总和为 3)

我可以使用几条不同的行来完成此操作,但我想知道 LINQ 是否能够以更简洁的方式完成此操作。

4

4 回答 4

1

不,LINQ 不适合这样做。这是可能的,但您基本上必须使用该Aggregate函数并提供您自己的聚合创建委托。这样做要简单得多(更不用说更容易理解):

int sum = 0;

foreach(var item in collection)
{    
    sum += item.Value;

    if (sum >= targetValue) return item;
}

return null;
于 2012-07-14T04:59:18.767 回答
0

LINQ 通常不鼓励元素之间的相互依赖关系(在这种情况下,每个元素都需要对其之前的元素总和可见)。

编写一个循环来执行此操作要容易得多和清晰得多。您可以将其放在扩展方法后面以保持功能感:

public static Foo FirstBeyondSum(this IEnumerable<Foo> source, int value)
{
    var sum = 0;

    foreach(var item in source)
    {
        sum += item.Value;

        if(sum >= value)
        {
            return item;
        }
    }

    return null;
}

用法:

var firstFooBeyond3 = foos.FirstBeyondSum(3);
于 2012-07-14T05:09:54.907 回答
0

我不知道为什么人们一直告诉你 LINQ 不适合这个......

    var sum = 0;
    return collection.FirstOrDefault(item => (sum += item.Value) >= targetValue);

也许一个 > 而不是 >= 取决于边缘情况,但你明白了......

或者:

return collection.FirstOrDefault(item =>
    {
        sum += item.Value;
        return (sum += item.Value) >= targetValue;
    });

如果您不喜欢 (sum += item.Value) >= targetValue hack...

于 2012-07-14T05:34:40.660 回答
0

确切的问题是:

我可以使用几条不同的行来完成此操作,但我想知道 LINQ 是否能够以更简洁的方式完成此操作。

OP 已经通过使用 LINQ 解决了这个问题,并且想知道是否有更好的 LINQ 解决方案。因此,他希望看到一个 LINQ 解决方案,这样他就可以评估它是否比不使用 LINQ 更好地解决了他的问题。

所以,这是我能想到的最好的 LINQ 解决方案。即使结果证明它比他的代码效率低,这仍然可以回答他的问题,即 LINQ 是否能够更简洁地做到这一点,从而回答他的确切问题。

此外,OP 可以评估是否使用 LINQ 的最佳方法是提供一个示例。我不明白他为什么不能使用 LINQ。

要从集合中获取项目:

var item = collection
    .Where((f,i) => value >= collection.Take(i + 1).Sum (c => c.Value))
    .Last();

如果您正在寻找该项目的索引:

var index = collection.IndexOf(
     collection.Where((f,i) => value >= collection.Take(i + 1).Sum (c => c.Value))
    .Last());
于 2012-07-14T18:16:34.400 回答