在Dart中克隆列表,地图或集

时间:2014-02-13 03:17:01

标签: collections dart clone

来自Java背景:“克隆”Dart ListMapSet的推荐方法是什么?

12 个答案:

答案 0 :(得分:33)

在Java中使用clone()是棘手且有问题的 1,2 。实际上,clone()是一个复制构造函数,为此,Dart ListMapSet类型都有一个名为.from()的{​​{3}}执行named constructor;例如给出这些声明

  Map<String, int> numMoons, moreMoons;
  numMoons = const <String,int>{ 'Mars' : 2, 'Jupiter' : 27 };
  List<String> planets, morePlanets;

您可以像这样使用.from()

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

请注意,List.from()通常更接受迭代器,而不仅仅是List

为了完整起见,我应该提到dart:html Node类定义shallow copy方法。


1 J. Bloch,“ Effective Java ”第2版,第11项。
2 clone()。从这里引用 3 。引用文章:

  
    

如果您已经阅读了我的书中有关克隆的项目,特别是如果您在这些内容之间进行了阅读,您将会知道我认为克隆已经深受打击。 --- J.Bloch

  

3 B. Venners, "Josh Bloch on Design: Copy Constructor versus Cloning", 2002

答案 1 :(得分:22)

如果您使用的是dart> 2.3.0,则可以使用传播运算符,例如:

List<int> a = [1,2,3];
List<int> b = [...a]; // copy of a

答案 2 :(得分:5)

使用新版本的飞镖,克隆地图或列表变得非常容易。 您可以尝试使用此方法对List和Map进行深层克隆。

对于列表

List a = ['x','y', 'z'];
List b = [...a];

对于地图

Map mapA = {"a":"b"};
Map mapB = {...mapA};

我希望有人能对此有所帮助。

答案 3 :(得分:4)

Map.from()仅适用于一维地图。

要在飞镖中在没有参考的情况下复制多维地图,请使用以下方法


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

答案 4 :(得分:3)

对于列表和集合,我通常使用

ActionListener

@kzhdev提到的警告是List<String> clone = []..addAll(originalList); addAll()

  

[不要]真的不能克隆。他们在新的地图/列表/集合中添加参考。

我通常可以,但是我会记住这一点。

答案 5 :(得分:1)

此解决方案应该有效:

列表list1 = [1,2,3,4];

列表list2 = list1.map((element)=> element).toList();

用于列表,但对于地图等应相同,如果列表末尾,请记住添加到列表

答案 6 :(得分:1)

最适合我的解决方案:

List temp = {1,2,3,4}
List platforms = json.decode(json.encode(parent.platforms));

答案 7 :(得分:1)

这是我的解决方案。我希望它可以帮助某人。

  factory Product.deepCopy(Product productToCopy) => new Product(
    productToCopy.id,
    productToCopy.title,
    productToCopy.description,
    productToCopy.price,
    productToCopy.imageUrl,
    productToCopy.isFavorite,
  );}

答案 8 :(得分:0)

给出的答案很好,但是请注意generate构造函数,如果您要“增长”固定长度的列表,例如:

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

答案 9 :(得分:0)

要复制Map 已过滤;

 var filteredNewCopy = filtered.map((key, value) => MapEntry(key, [...value]));

答案 10 :(得分:0)

制作完全隔离的副本没有 100% 防弹的方法,但 answer from Manish Dhruw 非常好。但是,它仅适用于包含简单变量类型和嵌套 Maps 的 Maps。

要将其扩展为与其他常见集合(例如 ListSet 以及它们的组合)一起使用,您可以使用类似下面的代码。< /p>

您实际上并不需要 DeepCopyable 类,但如果您想使用这些函数轻松地使自己的类“可深度复制”,它会很有用。

abstract class DeepCopyable{
  T deepCopy<T>();
}

List<T> listDeepCopy<T>(List list){
  List<T> newList = List<T>();

  list.forEach((value) {
    newList.add(
      value is Map ? mapDeepCopy(value) :
      value is List ? listDeepCopy(value) :
      value is Set ? setDeepCopy(value) :
      value is DeepCopyable ? value.deepCopy() :
      value
    );
  });

  return newList;
}

Set<T> setDeepCopy<T>(Set s){
  Set<T> newSet = Set<T>();

  s.forEach((value) {
    newSet.add(
      value is Map ? mapDeepCopy(value) :
      value is List ? listDeepCopy(value) :
      value is Set ? setDeepCopy(value) :
      value is DeepCopyable ? value.deepCopy() :
      value
    );
  });

  return newSet;
}


Map<K,V> mapDeepCopy<K,V>(Map<K,V> map){
  Map<K,V> newMap = Map<K,V>();

  map.forEach((key, value){
    newMap[key] =
      value is Map ? mapDeepCopy(value) :
      value is List ? listDeepCopy(value) :
      value is Set ? setDeepCopy(value) :
      value is DeepCopyable ? value.deepCopy() :
      value;
  });

  return newMap;
}

正如我所提到的,它显然仍然不是 100% 万无一失的 - 例如,您将丢失嵌套集合的类型信息。

答案 11 :(得分:-2)

对于深层复制(克隆),可以使用:

Map<String, dynamic> src = {'a': 123, 'b': 456};
Map<String, dynamic> copy = json.decode(json.encode(src));

但是可能会对性能有所担心。