如何删除飞镖列表中的重复项? list.distinct()?

时间:2012-08-19 22:52:23

标签: list dart

如何从列表中删除重复项而不用一套搞错?有像list.distinct()的东西吗?还是list.unique()?

void main() {
  print("Hello, World!");

  List<String> list = ['abc',"abc",'def'];
  list.forEach((f)=>print("this is list $f"));

  Set<String> set = new Set<String>.from(list);
  print("this is #0 ${list[0]}");
  set.forEach((f)=>print("set: $f"));

  List<String> l2= new List<String>.from(set);
  l2.forEach((f)=>print("This is new $f"));

}


Hello, World!
this is list abc
this is list abc
this is list def
this is #0 abc
set: abc
set: def
This is new abc
This is new def

编辑:thx的答案。  设置似乎更快!!但它丢失了项目的顺序:/

16 个答案:

答案 0 :(得分:32)

使用toSet,然后使用toList

  var ids = [1, 4, 4, 4, 5, 6, 6];
  var distinctIds = ids.toSet().toList();

[1、4、5、6]

答案 1 :(得分:18)

我发现提供的任何答案都没有帮助。 这通常是我要做的:

    final ids = myList.map((e) => e.id).toSet();
    myList.retainWhere((x) => ids.remove(x.id));

当然,您可以使用任何可唯一标识对象的属性,而不必是id字段。

此方法对于较丰富的对象特别有用。对于简单的原始类型,此处已经发布的一些答案很好。 此解决方案的另一个不错的副作用是,与此处提供的其他解决方案不同,此解决方案不会更改列表中原始项目的顺序,因此不会更改它们!

答案 2 :(得分:10)

Set可以,但是不能保留顺序。这是使用LinkedHashSet的另一种方法:

import "dart:collection";

void main() {
  List<String> arr = ["a", "a", "b", "c", "b", "d"];
  List<String> result = LinkedHashSet<String>.from(arr).toList();
  print(result); // => ["a", "b", "c", "d"]
}

https://api.dart.dev/stable/2.4.0/dart-collection/LinkedHashSet/LinkedHashSet.from.html

答案 3 :(得分:9)

尝试以下

List<String> duplicates = ["a","c","a"];

duplicates = duplicates.toSet().toList();

检查Dartpad链接- https://dartpad.dev/4d3a724429bbd605f4682b7da253a16e

答案 4 :(得分:6)

尝试使用queries包。

import 'package:queries/collections.dart';

void main() {
  List<String> list = ["a", "a", "b", "c", "b", "d"];
  var result = new Collection(list).distinct();
  print(result.toList());
}
[a, b, c, d]

答案 5 :(得分:6)

我将此添加到 atreeon's answer。对于想要将其与 Object 一起使用的任何人:

class MyObject{
  int id;

  MyObject(this.id);


  @override
  bool operator ==(Object other) {
    return other != null && other is MyObject && hashCode == other.hashCode;
  }


  @override
  int get hashCode => id;
}

main(){
   List<MyObject> list = [MyObject(1),MyObject(2),MyObject(1)];

   // The new list will be [MyObject(1),MyObject(2)]
   List<MyObject> newList = list.toSet().toList();
}

答案 6 :(得分:5)

我有一个名为Reactive-Dart的库,它包含许多用于终止和非终止序列的可组合运算符。对于您的场景,它看起来像这样:

final newList = [];
Observable
   .fromList(['abc', 'abc', 'def'])
   .distinct()
   .observe((next) => newList.add(next), () => print(newList));

产量:

[abc, def]

我应该补充一点,其他库也有类似的功能。检查github周围,我相信你会找到合适的东西。

答案 7 :(得分:4)

void uniqifyList(List<Dynamic> list) {
  for (int i = 0; i < list.length; i++) {
    Dynamic o = list[i];
    int index;
    // Remove duplicates
    do {
      index = list.indexOf(o, i+1);
      if (index != -1) {
        list.removeRange(index, 1);
      }
    } while (index != -1);
  }
}

void main() {
  List<String> list = ['abc', "abc", 'def'];
  print('$list');
  uniqifyList(list);
  print('$list');
}

提供输出:

[abc, abc, def]
[abc, def]

答案 8 :(得分:4)

使用dart 2.3及更高版本,您可以使用传播运算符执行此操作:

final ids = [1, 4, 4, 4, 5, 6, 6]; 
final distinctIds = [...{...ids}];

这是否比ids.toSet().toList()可读性更好,让读者自己决定:)

答案 9 :(得分:3)

如果要保持排序或要处理比原始类型更复杂的对象。将可见的ID存储到Set,并过滤掉集合中已经存在的ID。

final list = ['a', 'a', 'b'];
final seen = Set<String>();
final unique = list.where((str) => seen.add(str)).toList();

print(unique); // => ['a', 'b']

答案 10 :(得分:1)

这是另一种方式...

x

答案 11 :(得分:1)

对于 objects 的不同列表,您可以使用 Equatable 包。

示例:

// ignore: must_be_immutable
class User extends Equatable {
  int id;
  String name;

  User({this.id, this.name});

  @override
  List<Object> get props => [id];
}

List<User> items = [
  User(
    id: 1,
    name: "Omid",
  ),
  User(
    id: 2,
    name: "Raha",
  ),
  User(
    id: 1,
    name: "Omid",
  ),
  User(
    id: 2,
    name: "Raha",
  ),
];

print(items.toSet().toList());

输出:

[User(1), User(2)]

答案 12 :(得分:0)

这是可行的解决方案:

var sampleList = ['1', '2', '3', '3', '4', '4'];
//print('orignal: $sampleList');
sampleList = Set.of(sampleList).toList();
//print('processed: $sampleList');

输出:

orignal: [1, 2, 3, 3, 4, 4]
processed: [1, 2, 3, 4]

答案 13 :(得分:0)

对我而言,最佳实践之一是对数组进行排序,然后对其进行重复数据删除。想法是从低级语言窃取的。所以,

首先根据自己的需要进行排序,然后对彼此重复的相等值进行重复数据删除。

// easy example
void dedup<T>(List<T> list, {removeLast: true}) {
  int shift = removeLast ? 1 : 0;
  T compareItem;
  for (int i = list.length - 1; i >= 0; i--) {
    if (compareItem == (compareItem = list[i])) {
      list.removeAt(i + shift);
    }
  }
}

// harder example
void dedupBy<T, I>(List<T> list, I Function(T) compare, {removeLast: true}) {
  int shift = removeLast ? 1 : 0;
  I compareItem;
  for (int i = list.length - 1; i >= 0; i--) {
    if (compareItem == (compareItem = compare(list[i]))) {
      list.removeAt(i + shift);
    }
  }
}


void main() {
  List<List<int>> list = [[1], [1], [2, 1], [2, 2]];
  print('$list');
  dedupBy(list, (innerList) => innerList[0]);
  print('$list');

  print('\n removeLast: false');

  List<List<int>> list2 = [[1], [1], [2, 1], [2, 2]];
  print('$list2');
  dedupBy(list2, (innerList) => innerList[0], removeLast: false);
  print('$list2');
}

输出:

[[1], [1], [2, 1], [2, 2]]
[[1], [2, 1]]

removeLast: false
[[1], [1], [2, 1], [2, 2]]
[[1], [2, 2]]

答案 14 :(得分:0)

8年后,我想添加一个答案懒惰地

Iterable<T> removeDuplicates<T>(Iterable<T> iterable) sync* {
  Set<T> items = {};
  for (T item in iterable) {
    if (!items.contains(item)) yield item;
    items.add(item);
  }
}

您可以将其用于任何Iterable,而不仅仅是List。要从另一个列表或任何其他Iterable中获取一个列表,

List<String> list = ['abc', 'abc', 'def'];
List<String> newList = removeDuplicates(list).toList();

尽管此答案比简单执行[...{...list}];的代码更多,但是在进行一些额外处理时效率会更高。例如,假设您有一个包含一百万个项目的列表,并且想要删除重复项并获得前5个:

// This will process 5 items:
List<String> newList = removeDuplicates(list).take(5).toList();

// This will process a million items:
List<String> newList = [...{...list}];

这是我的fast_immutable_collections软件包的一部分,该软件包将很快发布到pub.dev。

答案 15 :(得分:-1)

这是我的解决方案

    List<T> removeDuplicates<T>(List<T> list, IsEqual isEqual) {
      List<T> output = [];
      for(var i = 0; i < list.length; i++) {
        bool found = false;
        for(var j = 0; j < output.length; j++) {
          if (isEqual(list[i], output[j])) {
            found = true;
          }
        }
        if (found) {
          output.add(list[i]);
        }
      }

      return output;
    }

像这样使用它:

  var theList = removeDuplicates(myOriginalList, (item1, item2) => item1.documentID == item2.documentID);

或...

  var theList = removeDuplicates(myOriginalList, (item1, item2) => item1.equals(item2));

或...