假设我有一个列表:
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
我想要一个包含2个元素的列表列表:
var chunks = [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']];
使用Dart做到这一点的好方法是什么?
答案 0 :(得分:11)
pairs(list) => list.isEmpty ? list : ([list.take(2)]..addAll(pairs(list.skip(2))));
答案 1 :(得分:8)
Quiver(版本> = 0.18)提供partition()
作为其iterables库的一部分(import'package:quiver / iterables.dart')。实现返回延迟计算的Iterable
,使其非常有效。用作:
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
var pairs = partition(letters, 2);
返回的pairs
将是Iterable<List>
,如下所示:
[['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']]
答案 2 :(得分:7)
这是另一种方式:
var chunks = [];
for (var i = 0; i < letters.length; i += 2) {
chunks.add(letters.sublist(i, i+2));
}
return chunks;
答案 3 :(得分:3)
这种方式适用于奇数长度列表:
var nums = [1, 2, 3, 4, 5];
var pairs = new List.generate(nums.length~/2, (i) => [nums[2 * i], nums[2 * i + 1]]);
如果列表长度不均匀,也许您可能想要抛出错误或提供填充值。
答案 4 :(得分:3)
我建议创建一对迭代,并使用.toList,如果你真的需要它作为列表。此解决方案也可以应用于任何可迭代的,而不仅仅是列表。首先,一个只适用于列表(长度均匀)的简单解决方案(如Robert King提供的解决方案):
new Iterable.generate(letters.length ~/ 2,
(i) => [letters[2*i], letters[2*i + 1]])
更通用的解决方案很复杂:
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))
似乎从流中创建对流实际上更容易,而不是从迭代中生成可迭代的对。
答案 5 :(得分:1)
这是一种方式:
letters.fold([[]], (list, x) {
return list.last.length == 2 ? (list..add([x])) : (list..last.add(x));
});
答案 6 :(得分:1)
对Seth的回答略有改进,使其可以使用任何列表或块大小:
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));
}
答案 7 :(得分:1)
另一种方式:
extension IterableExtensions<E> on Iterable<E> {
Iterable<List<E>> chunked(int chunkSize) sync* {
if (length <= 0) {
yield [];
return;
}
int skip = 0;
while (skip < length) {
final chunk = this.skip(skip).take(chunkSize);
yield chunk.toList(growable: false);
skip += chunkSize;
if (chunk.length < chunkSize) return;
}
}
}
测试:
void main() {
test("list chunked", () {
final emptyList = [];
final letters = ['a', 'b', 'c', 'd', 'e', 'f'];
final digits = List.generate(32, (index) => index);
print(emptyList.chunked(2));
print(letters.chunked(2));
print(digits.chunked(2));
print(emptyList.chunked(3));
print(letters.chunked(3));
print(digits.chunked(3));
print(emptyList.chunked(5));
print(letters.chunked(5));
print(digits.chunked(5));
});
}
输出:
([])
([a, b], [c, d], [e, f])
([0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], ..., [28, 29], [30, 31])
([])
([a, b, c], [d, e, f])
([0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], ..., [27, 28, 29], [30, 31])
([])
([a, b, c, d, e], [f])
([0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], ..., [25, 26, 27, 28, 29], [30, 31])
答案 8 :(得分:0)
另一种解决方案;
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 :(得分:0)
聚会迟到,但对于需要此功能的任何人:基于扩展的解决方案:
extension Windowed<E> on Iterable<E> {
Iterable<List<E>> window(int size) sync* {
if (size <= 0) throw ArgumentError.value(size, 'size', "can't be negative");
final Iterator<E> iterator = this.iterator;
while (iterator.moveNext()) {
final List<E> slice = [iterator.current];
for (int i = 1; i < size; i++) {
if (!iterator.moveNext()) break;
slice.add(iterator.current);
}
yield slice;
}
}
}
答案 10 :(得分:0)
在大小为 n 的相等块上拆分列表(最后一个块是剩余部分)
Iterable<List<T>> chunks<T>(List<T> lst, int n) sync* {
final gen = List.generate(lst.length ~/ n + 1, (e) => e * n);
for (int i in gen) {
if (i < lst.length)
yield lst.sublist(i, i + n < lst.length ? i + n : lst.length);
}
}
用法示例:
chunks([2, 3, 4, 5, 6, 7, 5, 20, 33], 4).forEach(print);
chunks(['a', 'b', 'c'], 2).forEach(print);
答案 11 :(得分:0)
这是使用索引 for 循环和泛型的旧式解决方案:
List<List<T>> _generateChunks<T>(List<T> inList, int chunkSize) {
List<List<T>> outList = [];
List<T> tmpList = [];
int counter = 0;
for (int current = 0; current < inList.length; current++) {
if (counter != chunkSize) {
tmpList.add(inList[current]);
counter++;
}
if (counter == chunkSize || current == inList.length - 1) {
outList.add(tmpList.toList());
tmpList.clear();
counter = 0;
}
}
return outList;
}
使用示例
main() {
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
int chunkSize = 2;
List<List<String>> chunks = _generateChunks(letters, chunkSize);
print(chunks);
}
输出为:
[[a, b], [c, d], [e, f], [g, h]]
答案 12 :(得分:0)
我找到了一个简单的解决方案:
var subList = mylist.take(3); // take 3 items first
var subList = mylist.skip(2).take(3); // take [2..5] items
答案 13 :(得分:-1)
该函数返回给定块大小的原始数组中的子列表。
LoginActivity