78

我怎样才能轻松地将ListDart 中的 a 变平?

例如:

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

4

6 回答 6

151

我知道的最简单的方法是使用Iterable.expand()标识函数。expand()获取 Iterable 的每个元素,对其执行一个函数,返回一个 iterable(“扩展”部分),然后连接结果。在其他语言中,它可能被称为 flatMap。

因此,通过使用标识函数,expand 只会连接项目。如果你真的想要一个列表,那么使用toList().

var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var flat = a.expand((i) => i).toList();
于 2013-03-14T15:30:49.027 回答
8

我认为没有内置方法,但您始终可以将其减少为单个值:

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));
于 2013-03-14T15:23:39.763 回答
7

使用 Dart 2.3 或更高版本,您可以改为使用 collection-for和 spread 运算符来轻松展平列表。我个人觉得它比使用更具可读性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);
print(b); // Prints: [1, 2, 3, a, b, c, true, false, true] 

如果有需要递归展平的嵌套列表,您可以使用:

List<T> flattenDeep<T>(Iterable<dynamic> 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);
print(b) // Prints: [1, 2, 3, a, b, c, true, false, true] 
于 2020-12-25T07:04:11.773 回答
5

您可以使用生成器有效地做到这一点:

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);

于 2019-11-14T04:06:26.490 回答
3

使用 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;
}

此致,

塞巴斯蒂安

于 2014-03-08T05:24:45.730 回答
1

您可以尝试这种递归解决方案,它也允许单个元素并展平深度嵌套的列表。

List flatten(List arr) => 
  arr.fold([], (value, element) => 
   [
     ...value, 
     ...(element is List ? flatten(element) : [element])
   ]);

于 2021-01-05T07:37:18.227 回答