lib/collections: add `Collection::has_exactly`
authorJean Privat <jean@pryen.org>
Wed, 26 Nov 2014 20:42:42 +0000 (15:42 -0500)
committerJean Privat <jean@pryen.org>
Wed, 26 Nov 2014 20:46:45 +0000 (15:46 -0500)
Signed-off-by: Jean Privat <jean@pryen.org>

lib/standard/collection/abstract_collection.nit

index 9d79de9..fa16295 100644 (file)
@@ -140,6 +140,31 @@ interface Collection[E]
                for x in other do if not has(x) then return false
                return true
        end
+
+       # Does the collection contain exactly all the elements of `other`?
+       #
+       # The same elements must be present in both `self` and `other`,
+       # but the order of the elements in the collections are not considered.
+       #
+       #    assert [1..3].has_exactly([3,1,2]) == true  # the same elements
+       #    assert [1..3].has_exactly([3,1])   == false # 2 is not in the array
+       #    assert [1..2].has_exactly([3,1,2]) == false # 3 is not in the range
+       #
+       # Repeated elements must be present in both collections in the same amount.
+       # So basically it is a multi-set comparison.
+       #
+       #    assert [1,2,3,2].has_exactly([1,2,2,3]) == true  # the same elements
+       #    assert [1,2,3,2].has_exactly([1,2,3])   == false # more 2 in the first array
+       #    assert [1,2,3].has_exactly([1,2,2,3])   == false # more 2 in the second array
+       #
+       # Note that the default implementation is general and correct for any lawful Collections.
+       # It is memory-efficient but relies on `count` so may be CPU-inefficient for some kind of collections.
+       fun has_exactly(other: Collection[E]): Bool
+       do
+               if length != other.length then return false
+               for e in self do if self.count(e) != other.count(e) then return false
+               return true
+       end
 end
 
 # Instances of the Iterator class generates a series of elements, one at a time.