如何在Dart中合并两个列表?

208

我在想,有没有一种简单的方法可以在Dart中连接两个列表以创建一个全新的列表对象。我找不到任何东西,像这样的东西:

我的列表:

list1 = [1, 2, 3]
list2 = [4, 5, 6]

我尝试过:

var newList = list1 + list2;

我想要合并输出以下内容:

[1, 2, 3, 4, 5, 6]
14个回答

460

你可以使用:

var newList = new List.from(list1)..addAll(list2);

如果您有多个列表,可以使用:

var newList = [list1, list2, list3].expand((x) => x).toList()

从Dart 2开始,您现在可以使用+

var newList = list1 + list2 + list3;

从Dart 2.3版本开始,您可以使用扩展运算符:

var newList = [...list1, ...list2, ...list3];

29
一种可轻松连接多个列表的替代方法是:[list1, list2, list3, ...].expand((x) => x).toList() - Florian Loitsch
6
请注意,+ 运算符不能用于不同类型的列表。(在这种情况下,您会收到类似“type 'List<Widget>' is not a subtype of type 'List<Image>'” 的错误信息。)但是展开运算符对此情况非常有效。 - Sébastien
请问您能否检查一下这个问题并给我一些建议。https://stackoverflow.com/questions/62228799/flutter-merge-one-list-data-to-another-list#62228799 - Roxx
Dart 2.3 -> 太棒了!!! - SilSur
而性能方面呢?没有任何答案提到这个问题… - Dan Maia

22
现在支持使用+运算符将列表连接。 <例子:>
List<int> result = [0, 1, 2] + [3, 4, 5];

2
这是最新的答案。 - vladli

21

可能更加一致~

var list = []..addAll(list1)..addAll(list2);

3
“..addAll()”是什么意思?为什么不只用一个点呢?虽然我知道这个问题有些老了。 - Abbas.M
9
@Abbas.M ..是用于链式调用的,如果没有双点符号,你需要这样做: list = []; list.addAll(list1); list.addAll(list2); 就我看来,它的基本含义是调用此函数,但忽略其返回值,并继续在我们正在操作的对象上进行操作。 - csga5000

19
如果你想合并两个列表并删除重复项,你可以使用 {} 将最终的列表转换为一个 Set
var newList = {...list1, ...list2}.toList(); 

5
var newList = {...list1, ...list2}.toList(); - Sassan

10

Alexandres的答案是最好的,但如果你想在你的例子中使用+,你可以使用Darts运算符重载:

class MyList<T>{
  List<T> _internal = new List<T>();
  operator +(other) => new List<T>.from(_internal)..addAll(other);
  noSuchMethod(inv){
    //pass all calls to _internal
  }
}

那么:

var newMyList = myList1 + myList2;

有效的 :)


7

我收集了所有可能的方法,并使用benchmark_harness包进行基准测试。

根据结果,推荐的方法是:

  • final List<int> c = a + b;
  • final List<int> c = [...a, ...b];

以下是基准测试代码:

import 'package:benchmark_harness/benchmark_harness.dart';

List<int> a = [1, 2, 3];
List<int> b = [4, 5, 6];

class Benchmark1 extends BenchmarkBase {
  const Benchmark1() : super('c = a + b ');

  @override
  void run() {
    final List<int> c = a + b;
  }
}

class Benchmark2 extends BenchmarkBase {
  const Benchmark2() : super('c = a.followedBy(b).toList() ');

  @override
  void run() {
    final List<int> c = a.followedBy(b).toList();
  }
}

class Benchmark3 extends BenchmarkBase {
  const Benchmark3() : super('c = [a, b].expand((x) => x).toList() ');

  @override
  void run() {
    final List<int> c = [a, b].expand((x) => x).toList();
  }
}

class Benchmark4 extends BenchmarkBase {
  const Benchmark4() : super('c = [a, b].reduce((value, element) => value + element) ');

  @override
  void run() {
    final List<int> c = [a, b].reduce((value, element) => value + element);
  }
}

class Benchmark5 extends BenchmarkBase {
  const Benchmark5() : super('c = [a, b].fold([], (previousValue, element) => previousValue + element) ');

  @override
  void run() {
    final List<int> c = [a, b].fold([], (previousValue, element) => previousValue + element);
  }
}

class Benchmark6 extends BenchmarkBase {
  const Benchmark6() : super('a.addAll(b) ');

  @override
  void run() {
    a.addAll(b);
  }
}

class Benchmark7 extends BenchmarkBase {
  const Benchmark7() : super('c = <int>[...a, ...b] ');

  @override
  void run() {
    final List<int> c = <int>[...a, ...b];
  }
}

class Benchmark8 extends BenchmarkBase {
  const Benchmark8() : super('c = List.from(a)..addAll(b) ');

  @override
  void run() {
    final List<int> c = List.from(a)..addAll(b);
  }
}

void main() {
  // Benchmark1().report();
  // Benchmark2().report();
  // Benchmark3().report();
  // Benchmark4().report();
  // Benchmark5().report();
  // Benchmark6().report();
  // Benchmark7().report();
  Benchmark8().report();
}

结果如下:

c = a + b (RunTime): 0.8384643860155879 us.
c = a.followedBy(b).toList() (RunTime): 1.3018350015264015 us.
c = [a, b].expand((x) => x).toList() (RunTime): 2.194391139053011 us.
c = [a, b].reduce((value, element) => value + element) (RunTime): 1.1215188056273329 us.
c = [a, b].fold([], (previousValue, element) => previousValue + element) (RunTime): 1.7163271628511283 us.
a.addAll(b) (RunTime): 1.08603684815237 us.
c = <int>[...a, ...b] (RunTime): 0.8498483658053312 us.
c = List.from(a)..addAll(b) (RunTime): 0.9107294347150762 us.


4
如果您的列表中的某个元素可以为null,请使用...?运算符:
var newList = [
  ...?list1,
  ...?list2,
  ...?list3,
];

如果您想在列表中删除重复项:
var newList = {
  ...?list1,
  ...?list2,
  ...?list3,
}.toList();

3
这里有另一个例子:
import 'package:collection/collection.dart';

final x = [1, 2, 3];
final y = [4, 5, 6];
final z = [x, y].flattened // Iterable<int>
final result = z.toList();

请注意,flattened 是作为 Iterable<Iterable<T>> 的扩展定义的,因此也适用于其他可迭代对象。

1
这段代码来自于集合包,现在已经成为Flutter SDK的一部分,所以不要忘记导入import 'package:collection/collection.dart'; - Alexander Kremenchuk

3

addAll 是合并两个列表最常用的方式。

但是如果要连接多个列表,可以使用以下三个函数之一(下面是 示例):

  • expand - 将 Iterable 的每个元素展开为零个或多个元素,
  • fold - 通过迭代地将集合中的每个元素与现有值结合,将集合缩减为单个值,
  • reduce - 使用提供的函数迭代地组合集合的元素,将集合缩减为单个值。
void main() {
  List<int> a = [1,2,3];
  List<int> b = [4,5];
  List<int> c = [6];
  List<List<int>> abc = [a,b,c]; // list of lists: [ [1,2,3], [4,5], [6] ]
  List<int> ints = abc.expand((x) => x).toList();
  List<int> ints2 = abc.reduce((list1,list2) => list1 + list2);
  List<int> ints3 = abc.fold([], (prev, curr) => prev + curr); // initial value is []
  print(ints);  // [1,2,3,4,5,6]
  print(ints2); // [1,2,3,4,5,6]
  print(ints3); // [1,2,3,4,5,6]
}

3

对于Dart 2.3+和来自JavaScript社区的人:

var mergedList = [...listX, ...listY, ...listZ].toSet(); 

toSet()方法将过滤并返回唯一的元素。


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