我非常喜欢飞镖的列表操作功能。但是,我经常发现自己处于需要分区的状态。 function,其中列表根据布尔条件分为两部分。含义与.where
相同,但不会丢弃虚假的内容。
明显的实施:
Iterable partition(Iterable list, filter) {
var matches = [];
var nonMatches = [];
list.forEach((e) {
if (filter(e)) {
matches.add(e);
} else {
nonMatches.add(e);
}
});
return [matches, nonMatches];
}
但是,我也喜欢where
正在返回的懒惰迭代。
另一种实现方式是使用集合:
Iterable partition(Iterable list, filter) {
var matches = list.where(filter);
var nonMatches = list.toSet().difference(matches.toSet()).toList();
return [matches, nonMatches];
}
我很高兴看到如何做一个优雅的懒惰实现(如果它很容易)。
我相信从列表构建一个集合是一个O(n)
操作,所以这两个实现的效率不应该太大。评论就是这样。
更新
设定的实施是有缺陷的。我不确切地知道它为什么不起作用,但nonMatches
不包含matches
中未包含的所有数字。
答案 0 :(得分:3)
怎么样:
Iterable partition(Iterable list, filter) {
return [list.where((e) => filter(e)), list.where((e) => !filter(e))];
}
此致 罗伯特
答案 1 :(得分:2)
您可以将其无缝混合到视图中,例如UnmodifiableListView
:
import "package:unittest/unittest.dart";
import "dart:collection";
class Tuple<A,B> {
final A a;
final B b;
const Tuple(this.a, this.b);
String toString() {
return "(a: $a, b : $b)";
}
}
abstract class partitionMixin<RES, E>{
Iterable<E> where(bool test(E element));
Map<E, bool> _filterCache = new Map();
Tuple<RES,RES> partition(bool filter(E e)) {
bool cachedFilter(E e) {
if (_filterCache.containsKey(e)) return _filterCache[e];
else {
bool filterRes = filter(e);
_filterCache[e] = filterRes;
return filterRes;
}
}
return new Tuple(this.where(cachedFilter),
this.where((E e) => !cachedFilter(e)));
}
}
class ExtULV<E> = UnmodifiableListView<E> with
partitionMixin<ExtULV<E>,E>;
void main() {
test('Split one iterable in two"', () {
var foo = (e) => (e % 2) == 0;
var fooA = [2,4,6,8, 10, 12, 14];
var fooB = [1,3,5,7,9,11,13];
var fooRes = new Tuple(fooA, fooB);
var tested = new ExtULV([1,2,3,4,5,6,7,8,9,10,11,12,13,14]);
var testRes = tested.partition(foo);
print("fooRes : $fooRes\ntestRes: $testRes");
expect(testRes.a.toList().toString() == fooRes.a.toString(), true);
expect(testRes.b.toList().toString() == fooRes.b.toString(), true);
});
}
答案 2 :(得分:1)
如果你概括它就会变得更简单
Map groupedBy(f, list) {
var grouped = {};
for (var thing in list) {
grouped.putIfAbsent(f(thing), () => []).add(thing);
}
return grouped;
}
虽然让它变得懒惰并不容易。