How do I combine two lists in Dart?
ListGenericsDartConcatenationList Problem Overview
I was wondering if there was an easy way to concatenate two lists in dart to create a brand new list object. I couldn't find anything and something like this:
My list:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
I tried:
var newList = list1 + list2;
I wanted the combined output of:
[1, 2, 3, 4, 5, 6]
List Solutions
Solution 1 - List
You can use:
var newList = new List.from(list1)..addAll(list2);
If you have several lists you can use:
var newList = [list1, list2, list3].expand((x) => x).toList()
As of Dart 2 you can now use +
:
var newList = list1 + list2 + list3;
As of Dart 2.3 you can use the spread operator:
var newList = [...list1, ...list2, ...list3];
Solution 2 - List
maybe more consistent~
var list = []..addAll(list1)..addAll(list2);
Solution 3 - List
Dart now supports concatenation of lists using the +
operator.
Example:
List<int> result = [0, 1, 2] + [3, 4, 5];
Solution 4 - List
If you want to merge two lists and remove duplicates could do:
var newList = [...list1, ...list2].toSet().toList();
Solution 5 - List
Alexandres' answer is the best but if you wanted to use + like in your example you can use Darts operator overloading:
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
}
}
Then:
var newMyList = myList1 + myList2;
Is valid :)
Solution 6 - List
We can add all the elements of the other list to the existing list by the use of addAll()
method.
Using addAll()
method to add all the elements of another list to the existing list. and Appends all objects of iterable to the end of this list.
Extends the length of the list by the number of objects in iterable. Throws an UnsupportedError
if this list is fixed-length.
Creating lists
listone = [1,2,3]
listtwo = [4,5,6]
Combining lists
listone.addAll(listtwo);
Output:
[1,2,3,4,5,6]
Solution 7 - List
addAll
is the most common way to merge two lists.
But to concatenate list of lists, you can use any of these three functions (examples below):
- expand - Expands each element of an Iterable into zero or more elements,
- fold - Reduces a collection to a single value by iteratively combining each element of the collection with an existing value,
- reduce - Reduces a collection to a single value by iteratively combining elements of the collection using the provided function.
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]
}
Solution 8 - List
I collect all possible method and benchmark it using benchmark_harness package.
According to the result the recommended method is:
final List<int> c = a + b;
final List<int> c = [...a, ...b];
Here is the benchmark code:
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();
}
And the result:
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.
Solution 9 - List
No need to create a third list in my opinion...
Use this:
list1 = [1, 2, 3];
list2 = [4, 5, 6];
list1.addAll(list2);
print(list1);
// [1, 2, 3, 4, 5, 6] // is our final result!
Solution 10 - List
For Dart 2.3+ & the people from JavaScript community:
var mergedList = [...listX, ...listY, ...listZ].toSet();
toSet()
will filter and return only unique items.
Solution 11 - List
list1.followedBy(list2).toList();