36

Say I have the array [1,2,3,1,2,3] and I want to delete the first instance of (say) 2 from the array giving [1,3,1,2,3]. What's the easiest way?

3 Answers 3

71
li.delete_at(li.index(n) || li.length)

li[li.length] is out of range, so the || li.length handles the case where n isn't in the list.

irb(main):001:0> li = [1,2,3,1,2,3]
=> [1, 2, 3, 1, 2, 3]
irb(main):002:0> li.delete_at(li.index(2) || li.length)
=> 2
irb(main):003:0> li.delete_at(li.index(42) || li.length)
=> nil
irb(main):004:0> li
=> [1, 3, 1, 2, 3]
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you. I've been beating my head trying to express this elegantly.
I don't understand the || li.length can anyone please explain
Any value in ruby can be treated as a boolean value, with only false and nil evaluating to false. The double pipe syntax is a convenient shorthand. a || b means "a, unless it's nil, then b".
@erich2k8 so is li.length just another way of saying "don't delete anything (since length(n) is always beyond the array, and return 'nil'?"
@stevec Yes, exactly. This might be a bit confusing if encountered in the wild, but it's a way to make it a 1-liner that only does one traversal. Alternatively, you could store the index in a variable, then do the delete_at only if the variable value is non nil. Such variables are kind of just clutter after the check though. E.g. index = arr.index(3) && arr.delete_at(index) leaves that index variable around afterwards.
|
15

If || li.length is to avoid sending nil to li.delete_at (which would result in a TypeError), then a more readable version might look like this

li.delete_at li.index(42) unless li.index(42).nil?

1 Comment

You probably want to store li.index(42) in a variable, to prevent doing the search twice. The performance will be much better for large arrays.
8

Maybe it should become part of stdlib:

class Array
  def delete_first item
    delete_at(index(item) || length)
  end
end

2 Comments

Strongly agree. delete_at(index(item) || length) is super easy when you know it, but not obvious otherwise. delete_first is very nice.
Is there a place to (more formally) make suggestions for ruby?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.