如何在Dart中轻松展平List
?
例如:
var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var b = [1, 2, 3, 'a', 'b', 'c', true, false, true];
如何将a
变为b
,即将List
转换为包含所有这些值的{{1}}?
答案 0 :(得分:34)
我所知道的最简单方法是将Iterable.expand()
与身份功能一起使用。 expand()
获取Iterable的每个元素,对其执行返回可迭代(“扩展”部分)的函数,然后连接结果。在其他语言中,它可以被称为flatMap。
因此,通过使用标识函数,expand将只连接项目。如果您确实需要列表,请使用toList()
。
var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var flat = a.expand((i) => i).toList();
答案 1 :(得分:6)
我认为没有内置方法,但您可以随时将其减少为单个值:
var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var flatten = a.reduce([], (p, e) {
p.addAll(e);
return p;
});
print(flatten);
我希望addAll()
返回原始列表。目前它什么都不返回。如果这是真的,你可以写一个单一的班轮:a.reduce([], (p, e) => p.addAll(e))
。
或者,您可以循环浏览列表并添加:
var flatten = [];
a.forEach((e) => flatten.addAll(e));
答案 2 :(得分:3)
在 Dart 2.3 或更高版本中,您可以改为使用 collection-for
和展开运算符来轻松展平列表。我个人认为它比使用 Iterable.expand
更具可读性:
List<T> flatten<T>(Iterable<Iterable<T>> list) =>
[for (var sublist in list) ...sublist];
var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var b = flatten(a);
如果有嵌套列表需要递归展平,可以使用:
List<T> flattenDeep<T>(Iterable<Object> list) => [
for (var element in list)
if (element is! Iterable) element else ...flattenDeep(element),
];
var a = [[1, [[2], 3]], [[['a']], 'b', 'c'], [true, false, [true]]];
var b = flattenDeep(a);
答案 3 :(得分:1)
您可以尝试这种递归解决方案,它也允许单个元素并将深度嵌套的列表展平。
List flatten(List arr) =>
arr.fold([], (value, element) =>
[
...value,
...(element is List ? flatten(element) : [element])
]);
答案 4 :(得分:0)
使用expand方法的解决方案很适合满足这种情况:
expect(ListTools.getFlatList([[1],["hello",2],["test"]]),orderedEquals([1,"hello",2,"test"]));
但不适合那些
expect(ListTools.getFlatList([[1],["hello",2,["foo",5]],["test"]]),orderedEquals([1,"hello",2,"foo",5,"test"]));
expect(ListTools.getFlatList([1,["hello",2],"test"]),orderedEquals([1,"hello",2,"test"]));
为了满足这些测试用例,你需要更像递归的东西,如下面的函数:
List getFlatList(List list) {
List internalList = new List();
list.forEach((e) {
if (e is List) {
internalList.addAll(getFlatList(e));
} else {
internalList.add(e);
}
});
return internalList;
}
致以最诚挚的问候,
塞巴斯蒂安
答案 5 :(得分:0)
您可以使用生成器高效地执行此操作:
Iterable<T> flatten<T>(Iterable<Iterable<T>> items) sync* {
for (var i in items) {
yield* i;
}
}
Iterable<X> flatMap<T,X>(Iterable<Iterable<T>> items, X Function(T) f) =>
flatten(items).map(f);