【问题标题】:How to create a new List with unique elements from an old List如何使用旧列表中的独特元素创建新列表
【发布时间】:2021-08-14 21:08:46
【问题描述】:

我有一个这样的列表:

  var list = [
    {
      "type": "TypeA",
      "subType": ["A1", "A2"]
    },
    {
      "type": "TypeA",
      "subType": ["A1"]
    },
    {
      "type": "TypeB",
      "subType": ["B1"]
    },
    {
      "type": "TypeB",
      "subType": ["B2", "B3"]
    },
    {
      "type": "TypeC",
      "subType": ["C1"]
    }
  ];

如何使用旧列表中的独特元素创建新列表? 这是我想要的新列表:

  newList = [
    {
      "type": "TypeA",
      "subType": ["A1", "A2"]
    },
    {
      "type": "TypeB",
      "subType": ["B1", "B2", "B3"]
    },
    {
      "type": "TypeC",
      "subType": ["C1"]
    }
  ];

编辑:所有答案都有效,但是,我不知道如何使用模型类将它们应用到我的实际项目中

所以请帮帮我,这是完整的代码:

class ListModel {
  String type;
  List<String> subType;

  ListModel({this.type, this.subType});
}

void main() {
  List<ListModel> list = [
    ListModel(type: 'TypeA', subType: ['A1', 'A2']),
    ListModel(type: 'TypeA', subType: ['A1']),
    ListModel(type: 'TypeA', subType: []),
    ListModel(type: 'TypeB', subType: ['B1']),
    ListModel(type: 'TypeB', subType: ['B2', 'B3']),
    ListModel(type: 'TypeC', subType: ['C1']),
  ];

  //This is newList I want
  List<ListModel> newList = [
    ListModel(type: 'TypeA', subType: ['A1', 'A2']),
    ListModel(type: 'TypeB', subType: ['B1', 'B2', 'B3']),
    ListModel(type: 'TypeC', subType: ['C1']),
  ];
}

【问题讨论】:

标签: flutter dart


【解决方案1】:

创建一个扩展(你也可以在函数中使用它),

extension ListExt on List<Map> {
  bool mergeIfContains(Map element) {
    for (Map item in this) {
      if (item.containsKey("type") && (element["type"] == item["type"])) {
        var subTypes = [...item["subType"], ...element["subType"]];
        item["subType"] = Set.from(subTypes).toList();
        return true;
      }
    }
    return false;
  }
}

使用mergeIfContains 扩展,

var list = [
    {
      "type": "TypeA",
      "subType": ["A1", "A2"]
    },
    {
      "type": "TypeA",
      "subType": ["A1"]
    },
    {
      "type": "TypeB",
      "subType": ["B1"]
    },
    {
      "type": "TypeB",
      "subType": ["B2", "B3"]
    },
    {
      "type": "TypeC",
      "subType": ["C1"]
    }
  ];

  var dt = <Map>[];
  list.forEach((element) {
    if (!dt.mergeIfContains(element)) {
      dt.add(element);
    }
  });
  //TODO: dt is what you need
  print(dt);

对于数据模型,

class ListModel {
  final String type;
  final List<String> subTypes;

  ListModel({this.type, this.subTypes});

  @override
  String toString() => type;

  //This is very important, it replaces default equality check
  @override
  bool operator ==(other) => this.type == other.type;

  @override
  int get hashCode => super.hashCode;
}

现在您可以使用现有的列表方法,即contains

var data = [
    ListModel(type: 'TypeA', subTypes: ['A1', 'A2']),
    ListModel(type: 'TypeA', subTypes: ['A1']),
    ListModel(type: 'TypeA', subTypes: []),
    ListModel(type: 'TypeB', subTypes: ['B1']),
    ListModel(type: 'TypeB', subTypes: ['B2', 'B3']),
    ListModel(type: 'TypeC', subTypes: ['C1']),
  ];

  var dt = <ListModel>[];
  data.forEach((element) {
    if (dt.contains(element)) {
      var item = dt.firstWhere((e) => e == element);
      var subTypes = [...item.subTypes, ...element.subTypes];
      item.subTypes.clear();
      item.subTypes.addAll(Set.from(subTypes));
    } else {
      dt.add(element);
    }
  });
  //TODO: dt is what you need
  print(dt);

只是为了测试结果,可以将ListModel中的toString()替换为,

@override
String toString() => "$type => $subTypes";

【讨论】:

  • 感谢您的回答,我更新了问题,请帮助我更多xD
  • @Kel 我已经更新了使用数据模型实现的答案。如果您覆盖数据模型中的相等运算符,则无需创建扩展。
【解决方案2】:

此代码将为您工作

创建一个合并列表项的函数

我还将toString() 添加到 ListModel 以将其表示为字符串。

class ListModel {
  String type;
  List<String> subType;

  ListModel({this.type, this.subType});

  @override
  String toString() => 'ListModel(type: $type, subType: $subType)';
}

void main() {
  List<ListModel> list = [
    ListModel(type: 'TypeA', subType: ['A1', 'A2']),
    ListModel(type: 'TypeA', subType: ['A1']),
    ListModel(type: 'TypeA', subType: []),
    ListModel(type: 'TypeB', subType: ['B1']),
    ListModel(type: 'TypeB', subType: ['B2', 'B3']),
    ListModel(type: 'TypeC', subType: ['C1']),
  ];
  print(mergeListItems(list));
}

List<ListModel> mergeListItems(List<ListModel> list) {
  final newList = <ListModel>[];
  for (final model in list) {
    var index = newList.indexWhere((element) => element.type == model.type);
    if (index == -1) {
      newList.add(model);
      index = newList.length - 1;
    }
    for (final subType in model.subType) {
      final subtypeIndex =
          newList[index].subType.indexWhere((t) => t == subType);
      if (subtypeIndex == -1) newList[index].subType.add(subType);
    }
  }
  return newList;
}

结果

[ListModel(type: TypeA, subType: [A1, A2]), ListModel(type: TypeB, subType: [B1, B2, B3]), ListModel(type: TypeC, subType: [C1])]

【讨论】:

  • 感谢您的回答,我更新了问题,请帮助我更多:)
  • @Kel 我更新了我的答案,如果有帮助请检查并接受它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-02
  • 1970-01-01
  • 2017-10-17
  • 2013-12-16
  • 2016-09-07
  • 2020-01-25
  • 1970-01-01
相关资源
最近更新 更多