在Dart中,获取集合/列表中数字总和的最简单方法是什么?

109

我不喜欢无缘无故使用索引数组,只因为我认为它看起来很丑陋。是否有一种简洁的方式可以使用匿名函数进行求和?是否可能在不使用任何外部变量的情况下完成此操作?

14个回答

144

45
如果列表为空,这将失败。.fold()可以处理这种情况。 - Gazihan Alankus
如果List为空,则会出现错误Uncaught Error: Bad state: No element。在执行var sum = [1, 2, 3].reduce((a, b) => a + b);语句之前,我已经检查了List.length并且它对我起作用了。谢谢。 - Kamlesh
在使用自定义对象(例如Object.amount)时遇到了问题。 - wamae
5
这个答案已经过时,请参考这个链接 https://dev59.com/KWkv5IYBdhLWcg3wtTAN#68603277 - tmaihoff
你也可以使用这个来处理空列表:[1, 2, 3].fold(0, (e, t) => e + t); - M Karimi
显示剩余2条评论

136
int sum = [1, 2, 3].fold(0, (previous, current) => previous + current);

或者使用较短的变量名以减少占用空间:
int sum = [1, 2, 3].fold(0, (p, c) => p + c);

2
这应该是被接受的答案,因为它更适用于空列表。 - Ryan Deschamps
21
我更喜欢这个答案。为什么要有reduce呢?! 我:我想要.fold 妈妈:我们家已经有.fold了 家里的.fold就是.reduce - SEG.Veenstra

80

这是一个非常古老的问题,但是

实际上在2022年已经有了一个内置包。

只需导入即可。

import 'package:collection/collection.dart';

并在 Iterable 上调用 .sum 扩展方法。

FULL EXAMPLE

import 'package:collection/collection.dart';

void main() {
  final list = [1, 2, 3, 4];
  final sum = list.sum;
  print(sum); // prints 10
}
如果列表为空,.sum 返回 0。你可能也会对 list.average 感兴趣...

能否使用这种方法将列表中某个索引之前的所有数字相加? - Ariel H.
2
当然,你可以编写 list.sublist(0,3).sum,它将从索引 0 开始加总,直到排除索引 3。 - tmaihoff
此外,每个Iterable都有一个.take(int count)方法,让您省略下限的“0”,并创建一个惰性迭代器而不是列表(如果您不需要像“sum”获取器一样的所有项,则可能更具性能)。 - David Schneider

28

我仍然认为对于这个特定问题来说,这是更简洁易懂的。

num sum = 0;
[1, 2, 3].forEach((num e){sum += e;});
print(sum);
或者
num sum = 0;
for (num e in [1,2,3]) {
  sum += e;
}

这样的逻辑应该深植于每个程序员的本质。可惜如今的复制粘贴式程序员更忙于寻找辅助方法/包,而不是回归基础。恭喜并感谢您的分享。 - undefined

10

目前使用核心库没有一种干净的方法来完成它,但是如果你自己编写foldLeft,那么就有可能实现。

main() {
  var sum = foldLeft([1,2,3], 0, (val, entry) => val + entry);
  print(sum);
}

Dynamic foldLeft(Collection collection, Dynamic val, func) {
  collection.forEach((entry) => val = func(val, entry));
  return val;
}

我与Dart团队讨论过将foldLeft添加到核心集合中,希望它能很快被添加进去。


可以通过像Ruby一样在集合接口中添加一个inject函数来解决这个问题。 - Mark B
1
那是非常漂亮的代码,Lars。不仅是我所寻找的,现在我也理解了折叠功能。 - Phlox Midas
1
你可以使用匿名函数来完成它,无论是否需要任何库代码,只需将代码嵌入到foldLeft中即可。除非你过于聪明地使用递归,否则你几乎总是需要一个变量。或者,你也可以使用for(var each in...)而不是forEach,在for循环的主体中应用该函数。两种方法都可以。 - Alan Knight
2
请注意,已经有一些用于处理集合的外部库--其中一些在此线程中提到:http://groups.google.com/a/dartlang.org/group/misc/browse_thread/thread/0628027441ad1ac8/329810f9fa00a866 此外,集合库目前正在进行重大更改,我希望sum(或至少是fold/reduce)也能纳入其中。 - Ladicek

8

从 Dart 2.6 开始,你可以使用扩展方法在 List 上定义实用的方法。这适用于数字(示例 1),也适用于通用对象(示例 2)。

extension ListUtils<T> on List<T> {
  num sumBy(num f(T element)) {
    num sum = 0;
    for(var item in this) {
      sum += f(item);
    }
    return sum;
  }
}

示例1(对列表中的所有数字求和):

var numbers = [1, 2, 3];
var sum = numbers.sumBy((number) => number);

示例2(求所有Point.x字段的和):

var points = [Point(1, 2), Point(3, 4)];
var sum = points.sumBy((point) => point.x);

1
你好,扩展方法准备好了吗?我刚试着通过添加实验标志(Dart 2.6.1)来启用它们,但是然后失去了智能感知,并在IntelliJ中收到了一个Dart分析器异常。有什么想法吗? - atreeon
@atreeon 我不记得添加任何标志,但请记得将您的Flutter、Dart插件更新到最新版本,并仔细检查您是否实际上使用了至少2.6.0版本。此外,扩展类(在本例中为ListUtils)需要在您尝试使用它的文件中导入。 - vovahost
我之前在一个独立的Dart应用程序中使用它,现在我刚刚升级到最新的Flutter,它显示我有2.5(我认为Flutter安装的版本与命令行运行的版本不同)...所以,最新版本的Flutter使用2.5???我很困惑! - atreeon
我搞定了!!这些扩展方法非常好用。 - atreeon

5

我只是想为 @tmaihoff 的答案(关于使用 collection.dart 包)添加一些小细节:

他所说的 sum getter 只适用于包含 num 值的可迭代对象,例如 List<int>Set<double>

如果你有一个由其他表示值的对象类型组成的列表(例如 MoneyDecimalRational 或其他任何类型),则必须将其映射为数字。例如,要计算字符串列表中字符的数量,可以执行以下操作:

// Returns 15.
['a', 'ab', 'abc', 'abcd', 'abcde'].map((e) => e.length).sum;

截至2022年,另一种方法是使用 fast_immutable_collections软件包的sumBy()方法:
// Returns 15.
['a', 'ab', 'abc', 'abcd', 'abcde'].sumBy((e) => e.length), 15);

注意:我是包的作者。

3
我建议您在通用工具文件中创建此函数。 T sum<T extends num>(T lhs, T rhs) => lhs + rhs; 由于int,double和float都扩展自num类,因此您可以使用该函数来对任何数字求和。
例如:
List<int> a = [1,2,3];
int result = a.reduce(sum);
print(result); // result will be 6

2

如果使用fold时出现double TypeError错误,您可以使用reduce函数:

var sum = [0.0, 4.5, 6.9].reduce((a, b) => a + b);

2

以下是我的方法:

void main() {
  int value = sumTwo([1, 4, 3, 43]);
  print(value);
}

int sumTwo(List < int > numbers) {
  int sum = 0;

  for (var i in numbers) {
    sum = sum + i;
  }
  return sum;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接