问题
Assume I have a list like:
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
I would like a list of lists of 2 elements each:
var chunks = [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']];
What's a good way to do this with Dart?
回答1:
Here is another way:
var chunks = [];
for (var i = 0; i < letters.length; i += 2) {
chunks.add(letters.sublist(i, i+2 > letters.length ? letters.length : i + 2));
}
return chunks;
回答2:
Quiver (version >= 0.18) supplies partition() as part of its iterables library (import 'package:quiver/iterables.dart'). The implementation returns lazily-computed Iterable, making it pretty efficient. Use as:
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
var pairs = partition(letters, 2);
The returned pairs will be an Iterable<List> that looks like:
[['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']]
回答3:
A slight improvement on Seth's answer to make it work with any list or chunk size:
var len = letters.length;
var size = 2;
var chunks = [];
for(var i = 0; i< len; i+= size)
{
var end = (i+size<len)?i+size:len;
chunks.add(letters.sublist(i,end));
}
回答4:
pairs(list) => list.isEmpty ? list : ([list.take(2)]..addAll(pairs(list.skip(2))));
回答5:
Here is one way:
letters.fold([[]], (list, x) {
return list.last.length == 2 ? (list..add([x])) : (list..last.add(x));
});
回答6:
This way works with odd length lists:
var nums = [1, 2, 3, 4, 5];
var pairs = new List.generate(nums.length~/2, (i) => [nums[2 * i], nums[2 * i + 1]]);
Perhaps you might want to throw an error or provide a filler value if the list length is not even.
回答7:
I would suggest creating an iterable of the pairs, and using .toList if you really need it as a list. This solution can also be applied to any iterable, not just a list. First, a simple solution that only works on lists (with even length)(Like the solution provided from Robert King):
new Iterable.generate(letters.length ~/ 2,
(i) => [letters[2*i], letters[2*i + 1]])
The more general solution is complex:
class mappedIterable extends Object implements Iterable with IterableMixin {
Function generator;
mappedIterable(Iterable source, Iterator this.generator(Iterator in));
Iterator get iterator => generator(source.iterator);
}
class Pairs implements Iterator {
Iterator _source;
List _current = null;
Pairs(Iterator this._source);
List get current => _current;
bool moveNext() {
bool result = _source.moveNext();
_current = [_source.current, (_source..moveNext()).current];
return result;
}
}
Iterable makePairs(Iterable source) =>
new mappedIterable(source, (sourceIterator) => new Pairs(sourceIterator));
print(makePairs(letters))
It seems like it is actually easier to make a stream of pairs from a stream, than to make an iterable of pairs from an iterable.
回答8:
another solution;
List chunk(List list, int chunkSize) {
List chunks = [];
int len = list.length;
for (var i = 0; i < len; i += chunkSize) {
int size = i+chunkSize;
chunks.add(list.sublist(i, size > len ? len : size));
}
return chunks;
}
List nums = [1,2,3,4,5];
print(chunk(nums, 2));
// [[1,2], [3,4], [5]]
回答9:
Influenced by @Alan's answer above and extending List, the equivalent of F# chunkedBySize and windowed and average could be:
import 'dart:collection';
class functionalList<E> extends ListBase<E> {
final List<E> l = [];
functionalList();
void set length(int newLength) { l.length = newLength; }
int get length => l.length;
E operator [](int index) => l[index];
void operator []=(int index, E value) { l[index] = value; }
chunkBySize(int size) => _chunkBySize(l, size);
windowed(int size) => _windowed(l, size);
get average => l.isEmpty
? 0
: l.fold(0, (t, e) => t + e) / l.length;
_chunkBySize(List list, int size) => list.isEmpty
? list
: ([list.take(size)]..addAll(_chunkBySize(list.skip(size), size)));
_windowed(List list, int size) => list.isEmpty
? list
: ([list.take(size)]..addAll(_windowed(list.skip(1), size)));
}
void main() {
var list = new functionalList();
list.addAll([1,2,3]);
print(list.chunkBySize(2));
}
The implementation can be seen here
来源:https://stackoverflow.com/questions/22274033/how-do-i-split-or-chunk-a-list-into-equal-parts-with-dart