【问题标题】:How to copy List<T> in dart without old reference?如何在没有旧参考的情况下在飞镖中复制 List<T>?
【发布时间】:2018-10-31 18:58:00
【问题描述】:

代码会解释一切:

//modal for list
class MyModal
{
 int myField1;
 List<MyModal> adjacentNodes;
 MyModal(this.myField1)
 {
  adjacentNodes= new List<MyModal>();
 }
}

//pre code
List<MyModal> originalList = new List<MyModal>();
originalList.add(new MyModal(1,"firstBuddy"));

//copying list
List<MyModal> secondList = new List<MyModal>();
secondList.addAll(originalList);

//Modifing copy list
secondList.adjacentNodes.add(new MyModal(2,"anotherBuddy"));

//Also modifies original list
print(originalList[0].childs.length); //prints 1, it should prints 0

如何在不影响原始列表的情况下对第二个列表进行更改?

【问题讨论】:

  • 您希望在第二个列表中进行哪些更改?仅添加/删除或同时更改不应在原始列表中产生影响的 MyModal 实例?
  • instance 的成员字段更改为我在上面的代码中解释的。

标签: dart flutter


【解决方案1】:
class MyModal {
  int myField1;
  String myField2;
  List<MyModal> adjacentNodes;
  MyModal(this.myField1,this.myField2);

  MyModal.clone(MyModal source) : 
      this.myField1 = source.myField1, 
      this.myField2 = source.myField2,
      this.adjacentNodes = source.adjacentNodes.map((item) => new MyModal.clone(item)).toList();
}

var secondList = originalList.map((item) => new MyModal.clone(item)).toList();

如果MyModal 的成员属于非原始类型,例如Stringintdoublenumbool,则clone() 方法需要克隆实例引用指向为好。

我认为对于您的用例,使用不可变值是一种更好的方法,例如使用 https://pub.dartlang.org/packages/built_value

【讨论】:

  • 仍在参考,变化正在反映
  • 取决于您所谈论的参考资料。无法自动创建列表内容的副本,只能创建列表本身的副本。
  • 更新的代码适用于 String、bool 等的成员,但不适用于用户定义的类型(我更新了我的问题,将 List 添加为成员)。
  • 这就是我在回答中所写的。如果你有对象的属性,那么你需要递归地克隆。请参阅我的更新答案。
【解决方案2】:

你可以使用 List.from() 函数。试试这个代码:

//modal for list
class MyModal {
  int myField1;
  String name;
  List<MyModal> adjacentNodes;
  MyModal(this.myField1, this.name) {
    adjacentNodes = new List<MyModal>();
  }
}

void runCopy() {
//pre code
  List<MyModal> originalList = new List<MyModal>();
  originalList.add(new MyModal(1, "firstBuddy"));

//copying list
  List<MyModal> secondList = List.from(originalList);
  secondList.addAll(originalList);
  print(originalList);
  print(secondList);
}

【讨论】:

  • 这只会执行对象的浅拷贝,尝试更改原始列表中 name 的值然后从它们两个打印它,它会是相同的。这仅适用于 int 或 string 等简单类型。所以,不,它不应该被选为正确答案。
【解决方案3】:

recommended 的方式是使用.toList 或列表文字。

List<int> source = [1];

List<int> copied = source.toList();
List<int> copied2 = [...source];

【讨论】:

    【解决方案4】:

    我刚刚使用了thelist2 = thelist1.toList();,它可以工作

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,List.from() 和 List.of() 不起作用。 我必须映射当前列表,从而创建一个新实例。

      List<CompanyBranchesDTO> get companyBranchesCopy {
        return companyBranches.map((e) =>
                CompanyBranchesDTO(id: e.id, name: e.name, isChecked: e.isChecked))
            .toList();
      }
      

      这样我就可以在需要的地方注入一个新实例。

      【讨论】:

        【解决方案6】:

        将其更改为 JSON,然后再次将其解析为对象。我知道这是肮脏的方式。

        (+) 它可以工作并且代码更少。 (-) 它不是解析方法。

        【讨论】:

          【解决方案7】:

          扩展运算符允许您将另一个列表中的值插入到集合中,如 dart 语言教程中所述: https://dart.dev/guides/language/language-tour#lists 所以你可以简单地这样做来避免浅拷贝:

          final List<MyType> newList = [...oldList];
          

          将此 dartpad 视为 POC:

          https://dartpad.dev/191c4767abc9540c63103044038562da?null_safety=true

          【讨论】:

          • 扩展运算符确实从列表中复制对象及其原始引用。
          【解决方案8】:
          List<T>.addall(T) worked for me
          

          List<mylist>.addall(oldlist)
          

          【讨论】:

          • 答案缺乏解释并且存在语法错误,这意味着您的代码将无法编译。请在发布答案之前确保您:1)有足够的解释来理解您的解决方案; 2)您的解决方案有效; 3) 好,但不是必需的——如果可能的话,指出 OP 出错的原因。
          猜你喜欢
          • 2018-12-28
          • 2020-02-12
          • 1970-01-01
          • 2012-07-27
          • 2013-09-18
          • 2021-11-06
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          相关资源
          最近更新 更多