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

Ger*_*ero 18 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
Run Code Online (Sandbox Code Playgroud)

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

atr*_*eon 80

使用toSet然后toList

  var ids = [1, 4, 4, 4, 5, 6, 6];
  var distinctIds = ids.toSet().toList();
Run Code Online (Sandbox Code Playgroud)

[1,4,5,6]

  • 现在这就是 Dart 方式(简短而强大)!谢谢你。 (15认同)
  • 请记住原始文档中的“集合中元素的顺序不能保证相同” (6认同)
  • @AleksTi它也适用于字符串,并且关于第二点:这就是整个操作的重点。 (5认同)
  • 这是明智的代码效率明智的选择。它也是高效的吗?我将在long for循环中使用它,以避免添加相同的元素。 (2认同)
  • 什么不起作用?var ids = ["abc", "def", "def"]; vardistinctIds = ids.toSet().toList(); 似乎删除了重复的“def” (2认同)

Bas*_*der 74

我没有发现任何提供的答案非常有帮助。以下是我通常做的:

    final ids = myList.map((e) => e.id).toSet();
    myList.retainWhere((x) => ids.remove(x.id));
Run Code Online (Sandbox Code Playgroud)

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

这种方法对于更丰富的对象特别有用。对于简单的原始类型,这里已经发布的一些答案很好。

该解决方案的另一个很好的副作用是,这里不像其他人提供的,这种解决方案并没有因为它就地修改列表更改列表中你原来项目的顺序!

  • 这是唯一适用于对象列表的答案谢谢伙计 (8认同)
  • 这就是我一直在寻找的解决方案,谢谢。但是,我有点困惑:为什么使用 [`.remove()`](https://api.dart.dev/stable/2.10.5/dart-core/Set/remove.html) 而不是 [` .add()`](https://api.dart.dev/stable/2.10.5/dart-core/Set/add.html)?似乎可以避免迭代列表两次:`final ids = Set(); myList.retainWhere((x) =&gt; ids.add(x.id))`。 (2认同)

Bai*_*aig 26

从对象列表中删除重复项:

class Stock {
  String? documentID; //key
  Make? make;
  Model? model;
  String? year;

  Stock({
    this.documentID,
    this.make,
    this.model,
    this.year,
  });
}
Run Code Online (Sandbox Code Playgroud)

库存列表,我们要从中删除重复的库存

List<Stock> stockList = [stock1, stock2, stock3];
Run Code Online (Sandbox Code Playgroud)

删除重复项

final ids = stockList.map((e) => e.documentID).toSet();
stockList.retainWhere((x) => ids.remove(x.documentID));
Run Code Online (Sandbox Code Playgroud)


Con*_*nce 25

//这个简单的方法效果很好

List<String> myArray = [];
myArray = ['x', 'w', 'x', 'y', 'o', 'x', 'y', 'y', 'r', 'a'];

myArray = myArray.toSet().toList();

print(myArray);
Run Code Online (Sandbox Code Playgroud)

// 结果=>myArray =['x','w','y','o','r', 'a']


小智 21

请尝试以下操作:

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

duplicates = duplicates.toSet().toList();
Run Code Online (Sandbox Code Playgroud)

在 Dartpad 上检查此代码

  • @TeeTracker:“第三支持”是什么意思? (3认同)

Nik*_*nen 16

如果您想保持排序或处理比原始类型更复杂的对象,请将看到的 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']
Run Code Online (Sandbox Code Playgroud)


jtl*_*lim 11

使用 Dart 2.3+,您可以使用扩展运算符来执行此操作:

final ids = [1, 4, 4, 4, 5, 6, 6];
final distinctIds = [...{...ids}];
Run Code Online (Sandbox Code Playgroud)

这比ids.toSet().toList()我让读者决定的可读性强还是弱:)


Omi*_*aha 11

对于不同的列表,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());
Run Code Online (Sandbox Code Playgroud)

输出:

[User(1), User(2)]
Run Code Online (Sandbox Code Playgroud)


Mar*_*ler 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"]
}
Run Code Online (Sandbox Code Playgroud)

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

  • 根据[文档](https://api.dart.dev/stable/2.4.0/dart-collection/LinkedHashSet-class.html),“LinkedHashSet还跟踪元素插入的顺序和迭代按照从第一个到最后一个插入顺序发生。” 如果顺序保留很重要,那么使用提供此保证的特定类型可能是有意义的,而不是依赖于(今天)默认实现的情况。虽然我没有看到文档明确保证默认的“Set()”将始终保留顺序,但它似乎不太可能改变,因为这可能会破坏相当多的内容。 (4认同)
  • `Set` 的默认实现是 `LinkedHashSet`,所以这不会改变任何内容 (3认同)

Bam*_*oUA 9

这是一个可行的解决方案:

var sampleList = ['1', '2', '3', '3', '4', '4'];
//print('original: $sampleList');
sampleList = Set.of(sampleList).toList();
//print('processed: $sampleList');
Run Code Online (Sandbox Code Playgroud)

输出:

original: [1, 2, 3, 3, 4, 4]
processed: [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)


mah*_*azi 9

我将此添加到atreeon 的答案中。对于任何想要使用它的人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();
}
Run Code Online (Sandbox Code Playgroud)


mez*_*oni 8

尝试使用查询包。

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());
}
Run Code Online (Sandbox Code Playgroud)
[a, b, c, d]
Run Code Online (Sandbox Code Playgroud)

从Dart 2.6.0开始,这可以轻松一点。

import 'package:enumerable/enumerable.dart';

void main() {
  final list = ["a", "a", "b", "c", "b", "d"];
  var query = list.distinct();
  print(query.toList());
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*rcG 7

使用fast_immutable_collections包:

[1, 2, 3, 2].distinct();
Run Code Online (Sandbox Code Playgroud)

或者

[1, 2, 3, 2].removeDuplicates().toList();
Run Code Online (Sandbox Code Playgroud)

注意:虽然distinct()返回一个新列表,removeDuplicates()通过返回Iterable. 这意味着当您进行一些额外处理时,它的效率要高得多。例如,假设您有一个包含一百万个项目的列表,并且您想要删除重复项并获取前五个:

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

// This will process a million items:
List<String> newList = list.distinct().sublist(0, 5);

// This will also process a million items:
List<String> newList = [...{...list}].sublist(0, 5);
Run Code Online (Sandbox Code Playgroud)

这两种方法都接受一个by参数。例如:

// Returns ["a", "yk", "xyz"]
["a", "yk", "xyz", "b", "xm"].removeDuplicates(by: (item) => item.length);
Run Code Online (Sandbox Code Playgroud)

如果您不想将包包含到项目中但需要惰性代码,这里是简化的removeDuplicates()

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:我是fast_immutable_collections包的作者之一。


Cut*_*tch 5

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');
}
Run Code Online (Sandbox Code Playgroud)

给出输出:

[abc, abc, def]
[abc, def]
Run Code Online (Sandbox Code Playgroud)


Joh*_*ans -12

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

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

产量:

[abc, def]
Run Code Online (Sandbox Code Playgroud)

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