如何从列表中删除重复项而不用一套搞错?有像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的答案。 设置似乎更快!!但它丢失了项目的顺序:/
答案 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));
或...