How can I compare Lists for equality in Dart?

2019-01-18 03:26发布

问题:

I'm comparing two lists in Dart like this:

main() {
    if ([1,2,3] == [1,2,3]) {
        print("Equal");
    } else {
        print("Not equal");
    }   
}

But they are never equal. There doesn't seem to be an equal() method in the Dart API to compare Lists or Collections. Is there a proper way to do this?

回答1:

To complete Gunter's answer: the recommended way to compare lists for equality (rather than identity) is by using the Equality classes from the following package

import 'package:collection/collection.dart';

Edit: prior to 1.13, it was import 'package:collection/equality.dart';

E.g.,

Function eq = const ListEquality().equals;
print(eq([1,'two',3], [1,'two',3])); // => true

The above prints true because the corresponding list elements that are identical(). If you want to (deeply) compare lists that might contain other collections then instead use:

Function deepEq = const DeepCollectionEquality().equals;
List list1 = [1, ['a',[]], 3];
List list2 = [1, ['a',[]], 3];
print(    eq(list1, list2)); // => false
print(deepEq(list1, list2)); // => true

There are other Equality classes that can be combined in many ways, including equality for Maps. You can even perform an unordered (deep) comparison of collections:

Function unOrdDeepEq = const DeepCollectionEquality.unordered().equals;
List list3 = [3, [[],'a'], 1];
print(unOrdDeepEq(list2, list3)); // => true

For details see the package API documentation. As usual, to use such a package you must list it in your pubspec.yaml:

dependencies:
  collection: any


回答2:

Collections in Dart have no inherent equality. Two sets are not equal, even if they contain exactly the same objects as elements.

The collection library provides methods to define such an equality. In this case, for example

IterableEquality().equals([1,2,3],[1,2,3])

is an equality that considers two lists equal exactly if they contain identical elements.



回答3:

I just stumbled upon this

import 'package:collection/equality.dart';

void main(List<String> args) {
  if (const IterableEquality().equals([1,2,3],[1,2,3])) {
  // if (const SetEquality().equals([1,2,3].toSet(),[1,2,3].toSet())) {
      print("Equal");
  } else {
      print("Not equal");
  }
}

more info https://github.com/dart-lang/bleeding_edge/tree/master/dart/pkg/collection



回答4:

While this question is rather old, the feature still hasn't landed natively in Dart. I had a need for deep equality comparison (List<List>), so I borrowed from above now with recursive call:

bool _listsAreEqual(list1, list2) {
 var i=-1;
 return list1.every((val) {
   i++;
   if(val is List && list2[i] is List) return _listsAreEqual(val,list2[i]);
   else return list2[i] == val;
 });
}

Note: this will still fail when mixing Collection types (ie List<Map>) - it just covers List<List<List>> and so-on.

Latest dart issue on this seems to be https://code.google.com/p/dart/issues/detail?id=2217 (last updated May 2013).



回答5:

Before things work, you can use this:

  /**
   * Returns true if the two given lists are equal.
   */
  bool _listsAreEqual(List one, List two) {
    var i = -1;
    return one.every((element) {
      i++;

      return two[i] == element;
    });
  }


回答6:

The Built Collections library offers immutable collections for Dart that include equality, hashing, and other goodies.

If you're doing something that requires equality there's a chance you'd be better off with immutability, too.

http://www.dartdocs.org/documentation/built_collection/0.3.1/index.html#built_collection/built_collection



回答7:

Would something like this work for you?

try {
    Expect.listEquals(list1, list2);
  } catch (var e) {
    print("lists aren't equal: $e");
  }

Example:

main() {
  List<int> list1 = [1, 2, 3, 4, 5];
  List<int> list2 = new List.from(list1);
  try {
    Expect.listEquals(list1, list2);
  } catch (var e) {
    print("lists aren't equal: $e");
  }
  list1.removeLast();
  try {
    Expect.listEquals(list1, list2);
  } catch (var e) {
    print("Lists aren't equal: $e");
  }
}

Second try prints:

Lists aren't equal: Expect.listEquals(list length, expected: <4>, actual: <5>) fails


回答8:

Another option is to use the package "queries".

import 'package:queries/collections.dart';

void main() {
  var list1 = [1, 2, 3];
  var list2 = [1, 2, 3];
  var col1 = new Collection(list1);
  var col2 = new Collection(list2);
  if (col1.sequenceEqual(col2)) {
    print("Lists equal");
  } else {
    print("Lists not equal");
  }
}

Function sequenceEqual declared in the following way:

bool sequenceEqual(IEnumerable<TSource> other,
      [IEqualityComparer<TSource> comparer])

This function can be used for comparing any data sequences. Also possible to use the user-defined data equality comparer. By default used built-in comparers.



标签: dart