How do I split or chunk a list into equal parts, with Dart?

心已入冬 提交于 2020-12-30 04:57:22

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!