112 votes

Comment aplatir une liste ?

Comment puis-je aplatir facilement un List dans Dart ?

Par exemple :

var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var b = [1, 2, 3, 'a', 'b', 'c', true, false, true];

Comment transformer a en b c'est-à-dire en un seul List contenant toutes ces valeurs ?

206voto

Justin Fagnani Points 4043

La méthode la plus simple que je connaisse est d'utiliser Iterable.expand() avec une fonction d'identité. expand() prend chaque élément d'un itérable, exécute sur lui une fonction qui renvoie un itérable (la partie "expand"), puis concatène les résultats. Dans d'autres langages, il peut être connu sous le nom de flatMap.

Ainsi, en utilisant une fonction d'identité, expand concaténera simplement les éléments. Si vous voulez vraiment une liste, utilisez toList() .

var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];
var flat = a.expand((i) => i).toList();

24voto

jamesdlin Points 13455

Avec Dart 2.3 ou une version ultérieure, vous pouvez utiliser collection- for et l'opérateur spread pour aplatir facilement une liste. Je trouve personnellement que c'est plus lisible que d'utiliser 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] 

S'il y a des listes imbriquées que vous devez aplatir récursivement, vous pouvez utiliser :

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]

11voto

Kai Sellgren Points 8423

Je ne pense pas qu'il existe une méthode intégrée pour cela, mais vous pouvez toujours le réduire à une seule valeur :

var a = [[1, 2, 3], ['a', 'b', 'c'], [true, false, true]];

var flatten = a.reduce([], (p, e) {
  p.addAll(e);
  return p;
});

print(flatten);

Je souhaite addAll() renverrait la liste originale. Actuellement, il ne renvoie rien. Si c'était le cas, vous pourriez écrire une seule ligne : a.reduce([], (p, e) => p.addAll(e)) .

Il est également possible de parcourir la liste en boucle et d'ajouter des éléments :

var flatten = [];
a.forEach((e) => flatten.addAll(e));

7voto

user48956 Points 1708

Vous pouvez le faire efficacement à l'aide d'un générateur :

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

3voto

Polysymbol Points 153

La solution avec la méthode expand est satisfaisante dans ce cas :

expect(ListTools.getFlatList([[1],["hello",2],["test"]]),orderedEquals([1,"hello",2,"test"]));

Mais pas pour ceux-là

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

Pour satisfaire ces cas de test, vous avez besoin de quelque chose de plus récursif comme la fonction suivante :

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

Je vous prie d'agréer, Madame, Monsieur, l'expression de mes salutations distinguées,

Sébastien

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X