在 Dart 中获取集合/列表中数字总和的最简洁方法是啥?

Posted

技术标签:

【中文标题】在 Dart 中获取集合/列表中数字总和的最简洁方法是啥?【英文标题】:What is the cleanest way to get the sum of numbers in a collection/list in Dart?在 Dart 中获取集合/列表中数字总和的最简洁方法是什么? 【发布时间】:2012-05-11 10:21:23 【问题描述】:

我不喜欢使用索引数组,因为我认为它看起来很丑。有没有一种用匿名函数求和的干净方法?不使用任何外部变量是否可以做到这一点?

【问题讨论】:

【参考方案1】:

没有像现在这样使用核心库的干净方法,但是如果您滚动自己的 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 中一样向集合接口添加注入函数来解决。 那里有一些非常漂亮的代码,Lars。它不仅是我要找的东西,现在我了解折叠了。 您当然可以使用匿名函数来实现,无论是否使用任何库代码,只需内联上面 foldLeft 中的代码即可。而且你几乎总是需要一个变量,除非你对递归非常聪明。或者,您也可以只使用 for(var each in...) 而不是 forEach,然后在 for 循环的主体中应用该函数。两者都可以。 请注意,已经有一些用于处理集合的外部库——其中一些在此线程中被提及:groups.google.com/a/dartlang.org/group/misc/browse_thread/… 此外,集合库目前正在经历严重的变化,我希望总和(或至少折叠/减少)正在进入它。【参考方案2】:

我仍然认为对于这个特定问题,这更清晰,更容易理解。

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;

【讨论】:

【参考方案3】:
int sum = [1, 2, 3].fold(0, (previous, current) => previous + current);

或者用更短的变量名来减少占用空间:

int sum = [1, 2, 3].fold(0, (p, c) => p + c);

【讨论】:

这应该是公认的答案,因为它更适用于空列表。 我更喜欢这个答案.. 为什么 reduce 甚至存在?!我:我要.fold 妈妈:我们家里已经有.fold .fold 在家里:.reduce【参考方案4】:

Dart 可迭代对象现在有一个 reduce 函数 (https://code.google.com/p/dart/issues/detail?id=1649),因此您可以在不定义自己的 fold 函数的情况下简单地进行求和:

var sum = [1, 2, 3].reduce((a, b) => a + b);

【讨论】:

如果列表为空,则会失败。 .fold() 处理这种情况。 如果List 为空,则会出现错误Uncaught Error: Bad state: No element。我在var sum = [1, 2, 3].reduce((a, b) => a + b); 声明之前检查了List.length,它对我有用。谢谢。 在使用自定义对象时遇到问题,例如对象.数量 这个答案已经过时了。请考虑这个***.com/a/68603277/8539278【参考方案5】:

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

【讨论】:

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

我建议您在任何常用实用程序文件中创建此函数。

T sum&lt;T extends num&gt;(T lhs, T rhs) =&gt; lhs + rhs;

int、double、float 扩展了 num 类,因此您可以使用该函数对任何数字求和。

例如,

List<int> a = [1,2,3];
int result = a.reduce(sum);
print(result); // result will be 6

【讨论】:

【参考方案7】:

在此分享我的方法:

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;

【讨论】:

【参考方案8】:

如果您计划对列表进行一些数学运算,则通过扩展 ListBase 创建另一个包含 .sum() 和其他运算的列表类型可能会有所帮助。其中一部分是inspired by this response 和performance tweaks from this response。

import 'dart:collection';
import 'dart:core';

class Vector<num> extends ListBase<num> 
  
  List<num> _list;
  Vector() : _list = new List<num>();
  Vector.fromList(List<num> lst): _list = lst;
  
  void set length(int l) 
    this._list.length=l;
  

  int get length => _list.length;
  
  num operator [](int index) => _list[index];

  void operator []=(int index, num value) 
    _list[index]=value;
  
  // Though not strictly necessary, for performance reasons
  // you should implement add and addAll.

  void add(num value) => _list.add(value);

  void addAll(Iterable<num> all) => _list.addAll(all);
  
  num sum() => _list.fold(0.0, (a, b) => a + b) as num;
  /// add additional vector functions here like min, max, mean, factorial, normalize etc


然后像这样使用它:

Vector vec1 = Vector();
vec1.add(1); 
print(vec1); // => [1]
vec1.addAll([2,3,4,5]); 
print(vec1); // => [1,2,3,4,5]
print(vec1.sum().toString()); // => 15
Vector vec = Vector.fromList([1.0,2.0,3.0,4.0,5.0]); // works for double too.
print(vec.sum().toString()); // => 15

【讨论】:

【参考方案9】:

对我来说干净利落的解决方案是:

var total => [1,2,3,4].fold(0, (e, t) => e + t); // result 10

【讨论】:

【参考方案10】:

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

2021年居然有内置包

只导入

import 'package:collection/collection.dart';

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

完整示例

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...感兴趣。

【讨论】:

非常优雅,谢谢【参考方案11】:

如果使用 fold 时出现double TypeError,则可以使用 reduce:

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

【讨论】:

【参考方案12】:

查找所有飞镖列表元素总和的不同方法,

方法一:使用循环: 这是最常用的方法。使用循环遍历列表并将列表的所有元素添加到最终的总和变量。我们在这里使用了一个 for 循环:

main(List<String> args) 
  var sum = 0;
  var given_list = [1, 2, 3, 4, 5];

  for (var i = 0; i < given_list.length; i++) 
    sum += given_list[i];
  

  print("Sum : $sum");

方法 2:使用 forEach : forEach 是另一种遍历列表的方法。我们还可以使用此方法找出 dart 列表中所有值的总和。它与上述方法类似。唯一的区别是我们不必初始化另一个变量 i 并且 list.length 不是必需的。

main(List<String> args) 
  var sum = 0;
  var given_list = [1, 2, 3, 4, 5];

  given_list.forEach((e) => sum += e);

  print("Sum : $sum");

方法 3:使用 reduce : reduce 方法使用给定的函数将列表的所有元素迭代地组合为一个值。我们可以使用这种方法来找出所有元素的总和,如下所示:

main(List<String> args) 
  var given_list = [1, 2, 3, 4, 5];

  var sum = given_list.reduce((value, element) => value + element);

  print("Sum : $sum");

方法 4:使用 fold : fold() 类似于 reduce。它使用函数将列表的所有元素迭代地组合成一个值。它取一个初始值,并根据前一个值计算最终值。

main(List<String> args) 
  var sum = 0;
  var given_list = [1,2,3,4,5];

  sum = given_list.fold(0, (previous, current) => previous + current);

  print("Sum : $sum");

更多详情:https://www.codevscolor.com/dart-find-sum-list-elements

【讨论】:

以上是关于在 Dart 中获取集合/列表中数字总和的最简洁方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

(Flutter/Dart) 如何修复使用 [ ] 显示列表中的数字

查找列表中哪个数字总和等于某个数字的算法

在 O(nlogk) 时间内找到长度为 n 的列表中总和小于 t 的 k 个元素

获取总和为X的数组的数字列表[重复]

保存从 Firestore 集合中的 JSON URL 获取的列表

在 Dart 中克​​隆列表、地图或集合