Aus einem Java-Hintergrund kommend: Was ist die empfohlene Methode, um einen Dart zu "klonen" List
, Map
und Set
?
Aus einem Java-Hintergrund kommend: Was ist die empfohlene Methode, um einen Dart zu "klonen" List
, Map
und Set
?
Antworten:
Die Verwendung clone()
in Java ist schwierig und fragwürdig 1,2 . Effektiv clone()
ist ein Kopierkonstruktor und dafür die Dart List
, Map
und Set
Arten haben jeweils einen Namen Konstruktor genannt , .from()
die eine ausführen flache Kopie ; zB angesichts dieser Erklärungen
Map<String, int> numMoons, moreMoons;
numMoons = const <String,int>{ 'Mars' : 2, 'Jupiter' : 27 };
List<String> planets, morePlanets;
Sie können .from()
wie folgt verwenden:
moreMoons = new Map<String,int>.from(numMoons)
..addAll({'Saturn' : 53 });
planets = new List<String>.from(numMoons.keys);
morePlanets = new List<String>.from(planets)
..add('Pluto');
Beachten Sie, dass List.from()
im Allgemeinen ein Iterator akzeptiert wird und nicht nur ein List
.
Der Vollständigkeit halber sollte ich erwähnen, dass die dart:html
Node
Klasse eine clone () -Methode definiert.
1 J. Bloch, " Effective Java ", 2. Aufl., Punkt 11.
2 B. Venners, " Josh Bloch über Design: Kopierkonstruktor versus Klonen ", 2002 . Von hier aus referenziert 3 . Zitat aus dem Artikel:
Wenn Sie den Artikel über das Klonen in meinem Buch gelesen haben, insbesondere wenn Sie zwischen den Zeilen lesen, werden Sie wissen, dass ich denke, dass der Klon tief gebrochen ist. --- J.Bloch
.from()
ist ein flacher Kopierkonstruktor. Um ganz klar zu sein, ich habe nie gesagt, dass .from()
eine Klonoperation durchgeführt wurde. Was ich schrieb, war clone()
eine Art Kopierkonstruktor.
List
, List<E>.of()
dass es besser sein könnte , wenn Sie den Typ des Originals kennen .
Für Listen und Sets verwende ich normalerweise
List<String> clone = []..addAll(originalList);
Die Einschränkung, wie @kzhdev erwähnt, ist das addAll()
undfrom()
Machen Sie keinen Klon. Sie fügen eine Referenz in die neue Karte / Liste / Menge ein.
Das ist normalerweise in Ordnung für mich, aber ich würde es mir merken.
Wenn Sie dart> 2.3.0 verwenden, können Sie den Spread-Operator wie folgt verwenden:
List<int> a = [1,2,3];
List<int> b = [...a]; // copy of a
Diese Lösung sollte funktionieren:
List list1 = [1,2,3,4];
List list2 = list1.map((element)=>element).toList();
Es ist für eine Liste, sollte aber für eine Karte usw. genauso funktionieren. Denken Sie daran, es zur Liste hinzuzufügen, wenn es am Ende eine Liste ist
Für Deep Copy (Klon) können Sie Folgendes verwenden:
Map<String, dynamic> src = {'a': 123, 'b': 456};
Map<String, dynamic> copy = json.decode(json.encode(src));
Es kann jedoch Bedenken hinsichtlich der Leistung geben.
Map.from () funktioniert nur für 1D-Karten.
Verwenden Sie die folgende Methode, um eine mehrdimensionale Karte ohne Referenz in Dart zu kopieren
Map<keyType, valueType> copyDeepMap( Map<keyType, valueType> map )
{
Map<keyType, valueType> newMap = {};
map.forEach
(
(key, value)
{
newMap[key] =( value is Map ) ? copyDeepMap(value) : value ;
}
);
return newMap;
}
Mit der neuen Version des Dart-Klonens einer Karte oder Liste wird das ganz einfach. Sie können diese Methode ausprobieren, um einen tiefen Klon von Liste und Karte zu erstellen.
Für Liste
List a = ['x','y', 'z'];
List b = [...a];
Für Karten
Map mapA = {"a":"b"};
Map mapB = {...mapA};
Ich hoffe jemand findet das hilfreich.
So kopieren Sie Map <String, List> gefiltert;
var filteredNewCopy = filtered.map((key, value) => MapEntry(key, [...value]));
Die gegebene Antwort ist gut, aber beachten Sie den generate
Konstruktor, der hilfreich ist, wenn Sie eine Liste mit fester Länge "vergrößern" möchten, z.
List<String> list = new List<String>(5);
int depth = 0; // a variable to track what index we're using
...
depth++;
if (list.length <= depth) {
list = new List<String>.generate(depth * 2,
(int index) => index < depth ? list[index] : null,
growable: false);
}