116

セットをいじらずにリストから重複を削除するにはどうすればよいですか?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

セットの方がずっと速いようです!! しかし、それはアイテムの順序を失います:/

4

18 に答える 18

347

使用toSetしてからtoList

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

結果:[1、4、5、6]

またはスプレッド演算子を使用する場合:

var distinctIds = [...{...ids}];
于 2018-07-20T16:32:01.140 に答える
106

提供された回答のどれも非常に役立つとは思いませんでした。これが私が一般的に行うことです:

final ids = Set();
myList.retainWhere((x) => ids.add(x.id));

もちろん、オブジェクトを一意に識別する任意の属性を使用できます。フィールドである必要はありませんid

他のアプローチに対する利点:

  • リストの元の順序を保持します
  • プリミティブ/ハッシュ可能なタイプだけでなく、リッチオブジェクトでも機能します
  • リスト全体をセットにコピーしてリストに戻す必要はありません

更新09/12/21
リストに対して拡張メソッドを1回宣言することもできます。

extension Unique<E, Id> on List<E> {
  List<E> unique([Id Function(E element)? id, bool inplace = true]) {
    final ids = Set();
    var list = inplace ? this : List<E>.from(this);
    list.retainWhere((x) => ids.add(id != null ? id(x) : x as Id));
    return list;
  }
}

この拡張方法は、私の元の答えと同じです。使用法:

// Use a lambda to map an object to its unique identifier.
myRichObjectList.unique((x) => x.id);
// Don't use a lambda for primitive/hashable types.
hashableValueList.unique();
于 2020-08-06T05:28:46.300 に答える
42

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

于 2019-07-29T18:07:25.370 に答える
26

次のことを試してください。

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

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

Dartpadでこのコードを確認してください。

于 2020-05-26T19:28:00.127 に答える
18

順序付けを継続したい場合、またはプリミティブ型よりも複雑なオブジェクトを処理している場合は、表示されたIDをセットに格納し、すでにセットに含まれているIDをフィルターで除外します

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

print(unique); // => ['a', 'b']
于 2019-09-30T11:36:39.980 に答える
14

私はこれを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();
}
于 2021-02-10T13:03:52.273 に答える
11

Dart 2.3以降を使用すると、スプレッド演算子を使用してこれを行うことができます。

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

ids.toSet().toList()これが私が読者に決定させるよりも読みやすいかどうか:)

于 2019-10-03T13:09:35.217 に答える
7

明確なリストについては、 Equatableパッケージobjectsを使用できます。

例:

// 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)]
于 2021-04-29T17:56:54.033 に答える
5

これが、実用的なソリューションです。

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

出力:

original: [1, 2, 3, 3, 4, 4]
processed: [1, 2, 3, 4]
于 2019-07-15T09:55:09.497 に答える
5

//この簡単な方法はうまく機能します

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

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

print(myArray);

//結果=>myArray= ['x'、'w'、'y'、'o'、'r'、'a']

于 2021-11-28T19:56:29.890 に答える
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]
于 2012-08-19T23:22:50.863 に答える
4

fast_immutable_collectionsパッケージの使用:

[1, 2, 3, 2].distinct();

または

[1, 2, 3, 2].removeDuplicates().toList();

注:distinct()新しいリストを返しますが、を返すremoveDuplicates()ことで遅延Iterableます。これは、追加の処理を行う場合にはるかに効率的であることを意味します。たとえば、100万個のアイテムを含むリストがあり、重複を削除して最初の5つを取得するとします。

// 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);

どちらのメソッドもbyパラメーターを受け入れます。例えば:

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

プロジェクトにパッケージを含めたくないが、怠惰なコードが必要な場合は、ここで簡略化しています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);
  }
}

注:私はfast_immutable_collectionsパッケージの作成者の1人です。

于 2020-12-16T14:32:43.597 に答える
1

私の場合、ベストプラクティスの1つは、アレイを並べ替えてから重複排除することです。アイデアは低水準言語から盗まれます。したがって、最初に自分で並べ替えを行い、次に互いに続く等しい値を重複排除します。

// 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]]
于 2019-12-17T05:15:19.183 に答える
1

これは別の方法です...

final reducedList = [];

list.reduce((value, element) {
    if (value != element) 
        reducedList.add(value);
    return element;
});

reducedList.add(list.last);

print(reducedList);
于 2020-07-27T03:08:09.607 に答える
0

わたしにはできる。

var list = [
 {"id": 1, "name": "Joshua"},
 {"id": 2, "name": "Joshua"},
 {"id": 3, "name": "Shinta"},
 {"id": 4, "name": "Shinta"},
 {"id": 5, "name": "Zaidan"}
];
list.removeWhere((element) => element.name == element.name.codeUnitAt(1));
list.sort((a, b) => a.name.compareTo(b.name));

出力:

[{"id": 1, "name": "Joshua"}, 
{"id": 3, "name": "Shinta"}, 
{"id": 5, "name": "Zaidan"}]
于 2021-12-09T01:03:59.510 に答える
0
List<Model> bigList = [];
List<ModelNew> newList = [];  

for (var element in bigList) {
      var list = newList.where((i) => i.type == element.type).toList();
      if(list.isEmpty){
       newList.add(element);
      }
    }
于 2022-03-05T18:08:36.157 に答える
-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));

また...

于 2020-12-21T23:27:49.740 に答える
-9

Reactive-Dartというライブラリがあり、シーケンスを終了および非終了するための多くの構成可能な演算子が含まれています。あなたのシナリオでは、次のようになります。

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

降伏:

[abc, def]

同様の機能を備えたライブラリが他にもあることを付け加えておきます。GitHubをチェックして、適切なものが見つかると確信しています。

于 2012-08-20T00:53:11.620 に答える