开发者

Array#delete, but return the array?

Is there a built-in method which performs the same function as Array#delete but returns self? I'd like to do it without using a block and clearer than an_ary.-([el]).

I could monkeypatch one, but it seems like a "compact with arguments" method would be a relatively common 开发者_如何学JAVAdesire?


If you want to mutate the original array, like delete, here are options:

ary.reject!{|e| e==42 }.something_else
ary.tap{|a| a.delete 42}.something_else
(ary.delete 42;ary).something_else
(ary-=[42]).something_else

If you want a new array to chain from:

ary.reject{|e| e==42 }.something_else
(ary-[42]).something_else


an_ary.-([el]) looks awful.

What about...

an_ary - [el]

?

The most natural way of dealing with mathematical operations is this...

4 - 2

Not this...

4.-(2)


array.reject{|element| element == value_of_element_to_be_deleted}


You can do

my_array.first(n) #1

my_array.last(n) #2

If the elements of the array you want to delete, are at the end (1) or at the beginning (2) of the array.


I had this same question for Array#delete_at that returned an array with the element at a specified index removed, which is why I ended up here. Looks like it isn't built in. In case anyone else is interested, I quickly wrote this monkey patch (I gave this virtually no thought regarding efficiency, and I originally didn't handle any cases such as negative indices or out of bounds indices...but then I decided to quick throw a couple in there):

class Array
  def remove_at(i)
    # handle index out of bounds by returning unchanged array
    return self if i >= self.length

    # remove the i-th element from the end if i is negative
    if i < 0
      i += self.length
      # handle index out of bounds by returning unchanged array
      return self if i < 0
    end

    # Return an array composed of the elements before the specified
    # index plus the elements after the specified index
    return self.first(i) + self.last(self.length - i - 1)
  end
end

test = [0,1,2,3,4,5]
puts test.remove_at(3).inspect
puts test.remove_at(5).inspect
puts test.remove_at(6).inspect
puts test.remove_at(-7).inspect
puts test.remove_at(-2).inspect

I had fun whipping this up, so I figured I might as well post it here :)


I prefer this way:

list = [1, 2, 3, 4, 5]
list.tap { |list| list.delete(2) } # => [1, 3, 4, 5]


The OP doesn't like the look of an_ary.-([el]) ... but it really does have a lot going for it.

True...it's a little ugly, but the minus method does the trick concisely, subtracting one array from the other:

ary = [1, 2, 99, 3]
ary.-([99])

or

odds = [1, 3, 5, 7, 9, 99]
ary.-(odds)

The advantage here is that it is completely chainable (unlike .delete or ary - odds), so you can do things like:

ary.-(odds).average

Once your eye finds the minus sign, it's much easier to read, understand, and visually spot typos than the .delete_if or .reject block constructs.

It also plays well with Ruby's safe navigation operator, &., if you might get nil instead of an array. That's something you can't do elegantly with subtracting arrays.

maybe_array&.-(odds)&.average
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜