From 066c8f501674e845f04d3afe56ff9a86b14ac1ac Mon Sep 17 00:00:00 2001 From: Tyler Rick Date: Wed, 8 Jul 2020 19:20:48 -0700 Subject: [PATCH] Add Array#delete_first, Array#delete_first_each --- lib/core/facets/array/delete_first.rb | 21 ++++++++++++++ lib/core/facets/array/remove.rb | 38 +++++++++++++++++++++++++ test/core/array/test_remove.rb | 41 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 lib/core/facets/array/delete_first.rb create mode 100644 lib/core/facets/array/remove.rb create mode 100644 test/core/array/test_remove.rb diff --git a/lib/core/facets/array/delete_first.rb b/lib/core/facets/array/delete_first.rb new file mode 100644 index 00000000..c7424b8f --- /dev/null +++ b/lib/core/facets/array/delete_first.rb @@ -0,0 +1,21 @@ +class Array + # Deletes first item from +self+ that is equal to +obj+. + # + # Returns the deleted item, or +nil+ if no matching item is found. + # + # If the optional code block is given, the result of the block is returned if + # the item is not found. + # + # a = [ "a", "b", "b", "b", "c" ] + # a.delete_first("b") #=> "b" + # a #=> ["a", "c"] + # a.delete("z") #=> nil + # a.delete("z") {"not found"} #=> "not found" + def delete_first(el) + i = index(el) + if i + delete_at(i) + end + end +end + diff --git a/lib/core/facets/array/remove.rb b/lib/core/facets/array/remove.rb new file mode 100644 index 00000000..5fb3a42e --- /dev/null +++ b/lib/core/facets/array/remove.rb @@ -0,0 +1,38 @@ +class Array + # Returns a new array that is a copy of the original array, removing the first occurrence of any + # item that also appears in +other_ary+. The order is preserved from the original array. + # + # If there are multiple occurrences of an item in +other_ary+, this removes that many occurrences + # from self. + # + # This is similar to `Array#-` and `Array#difference`, except that instead of removing _all_ + # matches, it only removes as many occurrences as there are in the +other_ary+: + # + # > [1, 1, 2].remove [1] + # => [1, 2] + # + # > [1, 1, 2].remove [1, 1, 1] + # => [2] + # + # > [1, 1, 2] - [1] + # => [2] + # + # > [1, 1, 2].difference [1] + # => [2] + # + def remove(other_ary) + dup.remove!(other_ary) + end + + # For each element of `other_ary`, deletes the _first_ element from self that is equal to that element + # (using `delete_at`, not `delete`). + # + # This is the in-place version of remove. + # + def remove!(other_ary) + other_ary.each do |el| + delete_first(el) + end + self + end +end diff --git a/test/core/array/test_remove.rb b/test/core/array/test_remove.rb new file mode 100644 index 00000000..558c753c --- /dev/null +++ b/test/core/array/test_remove.rb @@ -0,0 +1,41 @@ +covers 'facets/array/remove' + +test_case Array do + method :remove do + test do + a = [1,1,2,3] + a.difference([1]).assert == [ 2,3] + (a - [1]).assert == [ 2,3] + a.remove( [1]).assert == [ 1,2,3] + a.assert == [1,1,2,3] + end + + test do + a = [1,1,2,3] + (a - [1]).assert == [ 2,3] + a.remove([1, 1, 1]).assert == [ 2,3] + a.assert == [1,1,2,3] + end + + test 'example from Array#- docs' do + a = [ 1, 1, 2, 2, 3, 3, 4, 5 ] + (a - [ 1, 2, 4 ]).assert == [ 3, 3, 5 ] + a.remove([1, 2, 4 ]).assert == [ 1, 2, 3, 3, 5 ] + end + + test 'element that is not found' do + a = [1,1,2,3] + (a - [4]).assert == [1,1,2,3] + a.remove([4]).assert == [1,1,2,3] + a.assert == [1,1,2,3] + end + end + + method :remove! do + test do + a = [1,1,2,3] + a.remove!([1]).assert == [ 1,2,3] + a.assert == [ 1,2,3] + end + end +end