Katekko
Katekko

Reputation: 375

How can I distinct a complex object list in DART

I have one list of complex object. How can I distinct the list using their IDs?

I cant use toSet and similars, because the hashcode from the objects all are diferent.

Upvotes: 5

Views: 11457

Answers (2)

Andrey Kucher
Andrey Kucher

Reputation: 471

Try to use this extension (improved with Abion47's comment):

extension IterableExtension<T> on List<T> {
  Iterable<T> distinctBy(Object getCompareValue(T e)) {
    var idSet = <Object>{};
    var distinct = <T>[];
    for (var d in this) {
      if (idSet.add(getCompareValue(d))) {
        distinct.add(d);
      }
    }

    return distinct;
  }
}

Using:

var distinctList = someList.distinctBy((x) => x.oid);

Or you can use a hash there.

Upvotes: 11

Abion47
Abion47

Reputation: 24661

1) Vanilla Dart

Loop through the list, adding IDs to a set as you go. Whenever you add an ID to the set that didn't already exist, add that element to a new list of distinct values.

void main() {
  var list = [
    Data('a'),
    Data('a'),
    Data('b'),
    Data('c'),
  ];
  
  var idSet = <String>{};
  var distinct = <Data>[];
  for (var d in list) {
    if (idSet.add(d.id)) {
      distinct.add(d);
    }
  }
}

class Data {
  Data(this.id);
  final String id;
}

An alternative solution is to directly create an instance of HashSet (or LinkedHashSet if you care about insertion order) and manually specify the equality operations that will be used to determine uniqueness.

(This approach is potentially more performant than the first option since all of the items are added at once instead of looping through the list and adding each item individually. However, this is dependent on the native implementation of the class on each target platform, so it might not end up being more performant in practice.)

import 'dart:collection';

void main() {
  final list = [
    Data('a'),
    Data('a'),
    Data('b'),
    Data('c'),
  ];

  final dataSet = HashSet<Data>( // or LinkedHashSet
    equals: (a, b) => a.id == b.id,
    hashCode: (a) => a.id.hashCode,
  )..addAll(list);
}

class Data {
  Data(this.id);
  final String id;
}

2) Packages

Several packages exist that expand on default the Iterable utility methods, such as flinq or darq. They add a distinct method you can call to easily get a list of unique members of a list based on some property of the members.

import 'package:darq/darq.dart';

void main() {
  var list = [
    Data('a'),
    Data('a'),
    Data('b'),
    Data('c'),
  ];
  var distinct = list.distinct((d) => d.id).toList();
}

(Disclaimer, I am the maintainer of darq.)

Upvotes: 13

Related Questions