From 9d3e0e15823e448a6c05435bfa036f33181a8998 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 1 Nov 2016 14:16:56 -0700 Subject: [PATCH] Add EqualityMap and EqualitySet. (dart-lang/collection#35) --- pkgs/collection/CHANGELOG.md | 5 +++ pkgs/collection/lib/collection.dart | 2 + pkgs/collection/lib/src/equality_map.dart | 32 ++++++++++++++ pkgs/collection/lib/src/equality_set.dart | 32 ++++++++++++++ pkgs/collection/pubspec.yaml | 2 +- pkgs/collection/test/equality_map_test.dart | 37 ++++++++++++++++ pkgs/collection/test/equality_set_test.dart | 48 +++++++++++++++++++++ 7 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 pkgs/collection/lib/src/equality_map.dart create mode 100644 pkgs/collection/lib/src/equality_set.dart create mode 100644 pkgs/collection/test/equality_map_test.dart create mode 100644 pkgs/collection/test/equality_set_test.dart diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md index 74710a3d..fa102206 100644 --- a/pkgs/collection/CHANGELOG.md +++ b/pkgs/collection/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.11.0 + +* Add `EqualityMap` and `EqualitySet` classes which use `Equality` objects for + key and element equality, respectively. + ## 1.10.1 * `Set.difference` now takes a `Set` as argument. diff --git a/pkgs/collection/lib/collection.dart b/pkgs/collection/lib/collection.dart index 58d98f70..612508be 100644 --- a/pkgs/collection/lib/collection.dart +++ b/pkgs/collection/lib/collection.dart @@ -6,6 +6,8 @@ export "src/algorithms.dart"; export "src/canonicalized_map.dart"; export "src/comparators.dart"; export "src/equality.dart"; +export "src/equality_map.dart"; +export "src/equality_set.dart"; export "src/functions.dart"; export "src/iterable_zip.dart"; export "src/priority_queue.dart"; diff --git a/pkgs/collection/lib/src/equality_map.dart b/pkgs/collection/lib/src/equality_map.dart new file mode 100644 index 00000000..686e5bd9 --- /dev/null +++ b/pkgs/collection/lib/src/equality_map.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'equality.dart'; +import 'wrappers.dart'; + +/// A [Map] whose key equality is determined by an [Equality] object. +class EqualityMap extends DelegatingMap { + /// Creates a map with equality based on [equality]. + EqualityMap(Equality equality) + : super(new LinkedHashMap( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)); + + /// Creates a map with equality based on [equality] that contains all + /// key-value pairs of [other]. + /// + /// If [other] has multiple keys that are equivalent according to [equality], + /// the last one reached during iteration takes precedence. + EqualityMap.from(Equality equality, Map other) + : super(new LinkedHashMap( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)) { + addAll(other); + } +} + diff --git a/pkgs/collection/lib/src/equality_set.dart b/pkgs/collection/lib/src/equality_set.dart new file mode 100644 index 00000000..b0582ce6 --- /dev/null +++ b/pkgs/collection/lib/src/equality_set.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:collection'; + +import 'equality.dart'; +import 'wrappers.dart'; + +/// A [Map] whose key equality is determined by an [Equality] object. +class EqualitySet extends DelegatingSet { + /// Creates a set with equality based on [equality]. + EqualitySet(Equality equality) + : super(new LinkedHashSet( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)); + + /// Creates a set with equality based on [equality] that contains all + /// elements in [other]. + /// + /// If [other] has multiple values that are equivalent according to + /// [equality], the first one reached during iteration takes precedence. + EqualitySet.from(Equality equality, Iterable other) + : super(new LinkedHashSet( + equals: equality.equals, + hashCode: equality.hash, + isValidKey: equality.isValidKey)) { + addAll(other); + } +} + diff --git a/pkgs/collection/pubspec.yaml b/pkgs/collection/pubspec.yaml index f92b73d0..13b81f26 100644 --- a/pkgs/collection/pubspec.yaml +++ b/pkgs/collection/pubspec.yaml @@ -1,5 +1,5 @@ name: collection -version: 1.10.1 +version: 1.11.0 author: Dart Team description: Collections and utilities functions and classes related to collections. homepage: https://www.github.com/dart-lang/collection diff --git a/pkgs/collection/test/equality_map_test.dart b/pkgs/collection/test/equality_map_test.dart new file mode 100644 index 00000000..8225efd7 --- /dev/null +++ b/pkgs/collection/test/equality_map_test.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; +import 'package:test/test.dart'; + +void main() { + test("uses the given equality", () { + var map = new EqualityMap(const IterableEquality()); + expect(map, isEmpty); + + map[[1, 2, 3]] = 1; + expect(map, containsPair([1, 2, 3], 1)); + + map[[1, 2, 3]] = 2; + expect(map, containsPair([1, 2, 3], 2)); + + map[[2, 3, 4]] = 3; + expect(map, containsPair([1, 2, 3], 2)); + expect(map, containsPair([2, 3, 4], 3)); + }); + + test("EqualityMap.from() prefers the lattermost equivalent key", () { + var map = new EqualityMap.from(const IterableEquality(), { + [1, 2, 3]: 1, + [2, 3, 4]: 2, + [1, 2, 3]: 3, + [2, 3, 4]: 4, + [1, 2, 3]: 5, + [1, 2, 3]: 6, + }); + + expect(map, containsPair([1, 2, 3], 6)); + expect(map, containsPair([2, 3, 4], 4)); + }); +} diff --git a/pkgs/collection/test/equality_set_test.dart b/pkgs/collection/test/equality_set_test.dart new file mode 100644 index 00000000..1b20684b --- /dev/null +++ b/pkgs/collection/test/equality_set_test.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:collection/collection.dart'; +import 'package:test/test.dart'; + +void main() { + test("uses the given equality", () { + var set = new EqualitySet(const IterableEquality()); + expect(set, isEmpty); + + var list1 = [1, 2, 3]; + expect(set.add(list1), isTrue); + expect(set, contains([1, 2, 3])); + expect(set, contains(same(list1))); + + var list2 = [1, 2, 3]; + expect(set.add(list2), isFalse); + expect(set, contains([1, 2, 3])); + expect(set, contains(same(list1))); + expect(set, isNot(contains(same(list2)))); + + var list3 = [2, 3, 4]; + expect(set.add(list3), isTrue); + expect(set, contains(same(list1))); + expect(set, contains(same(list3))); + }); + + test("EqualitySet.from() prefers the lattermost equivalent value", () { + var list1 = [1, 2, 3]; + var list2 = [2, 3, 4]; + var list3 = [1, 2, 3]; + var list4 = [2, 3, 4]; + var list5 = [1, 2, 3]; + var list6 = [1, 2, 3]; + + var set = new EqualitySet.from(const IterableEquality(), + [list1, list2, list3, list4, list5, list6]); + + expect(set, contains(same(list1))); + expect(set, contains(same(list2))); + expect(set, isNot(contains(same(list3)))); + expect(set, isNot(contains(same(list4)))); + expect(set, isNot(contains(same(list5)))); + expect(set, isNot(contains(same(list6)))); + }); +}