How can I delete one element from an array by value

Go To StackoverFlow.com

294

I have an array of elements in Ruby

[2,4,6,3,8]

I need to remove elements with value 3 for example

How do I do that?

2012-04-05 19:19
by Tamik Soziev
i wonder why delete array.delete(3) not works within ruby on rails controlle - ImranNaqvi 2016-11-19 20:31
may be due to active record method deleteImranNaqvi 2016-11-19 20:31


416

I think I've figured it out:

a = [2,4,6,3,8]
a.delete(3)
2012-04-05 19:22
by Tamik Soziev
I personally like [1, 2, 3, 4, 5] - [3] which results in => [1, 2, 4, 5] from irb - Travis 2012-04-05 19:31
What if there are multiple entries of 3 and we wanted to delete only one of them? (this is related so asking this here might be best - Navneet 2012-10-18 18:24
@Navneet See http://stackoverflow.com/questions/4595305/delete-first-instance-of-matching-element-from-arra - user456584 2013-08-06 16:56
Just a heads up that .delete() will return the deleted value, not the modified array with the value removed - Joshua Pinter 2013-09-27 21:36
The other consequence to consider is that delete mutates the underlying array whereas - creates a new array (that is returned to you) without the deleted value. Depending on your use case either approach may make sense - srt32 2014-09-05 16:35
Something else to bear in mind is that [1,2,3,3] - [3] returns [1,2]. It will delete 'all' values of 3. Might or might not be what you need.. - Jules Copeland 2014-11-22 12:15
Also, array - subArray will not work for Array of Arrays, but array.delete(subArray) will do - Sachin 2016-04-05 12:42
@user3721428, delete(3) does not refer to the element in position 3 but instead deletes any element matching the integer 3. It will remove all occurrences of 3 and has nothing to do with the arrays index or position - bkunzi01 2016-06-11 15:33


190

Borrowing from Travis in the comments, this is a better answer:

I personally like [1, 2, 7, 4, 5] - [7] which results in => [1, 2, 4, 5] from irb

I modified his answer seeing that 3 was the third element in his example array. This could lead to some confusion for those who don't realize that 3 is in position 2 in the array.

2014-03-17 21:08
by Abram
As srt32 points out in the answer, there's an important distinction to make between using .delete and -. .delete will return the value that was removed from the Array, if any; - will not. So [ 1, 2, 3 ] - [ 2 ] will return [ 1, 3 ], while [ 1, 2, 3 ].delete( 2 ) will return 2 - Argus9 2014-10-23 16:45
array - subArray will not work for Array of Arrays, but array.delete(subArray) will do - Sachin 2016-04-05 12:41
The very important difference between [1,2,3] - [2] and [1,2,3].delete(2) is that delete method modifies the original array, while [1,2,3] - [3] creates a new array - Timothy Kovalev 2016-11-03 11:08


60

Another option:

a = [2,4,6,3,8]

a -= [3]

which results in

=> [2, 4, 6, 8] 
2014-09-18 02:23
by Steve


33

I'm not sure if anyone has stated this, but Array.delete() and -= value will delete every instance of the value passed to it within the Array. In order to delete the first instance of the particular element you could do something like

arr = [1,3,2,44,5]
arr.delete_at(arr.index(44))

#=> [1,3,2,5]

There could be a simpler way. I'm not saying this is best practice, but it is something that should be recognized.

2016-12-31 18:29
by Scott
I was looking for a way to do this and only delete one instance of the element incase of duplicates and this works great - xeroshogun 2017-10-10 20:20


24

I like the -=[4] way mentioned in other answers to delete the elements whose value are 4.

But there is this way:

irb(main):419:0> [2,4,6,3,8,6].delete_if{|i|i==6}
=> [2, 4, 3, 8]
irb(main):420:0>

mentioned somewhere in "Basic Array Operations", after it mentions the map function.

2015-06-26 01:36
by barlop
But can't you just use .delete(6)Zac 2016-10-06 16:00
@Zac of course but that answer has already been mentioned (as has the very concise -= way a-=[4] i.e. a=a-[4] . [3,4]-[4], which I said I liked), but I wanted to mention another possible way - barlop 2016-10-06 16:10
This method also has the advantage of returning the array instead of the deleted element - F.Webber 2019-02-08 21:18


20

Assuming you want to delete 3 by value at multiple places in an array, I think the ruby way to do this task would be to use the delete_if method:

[2,4,6,3,8,3].delete_if {|x| x == 3 } 

You can also use delete_if in removing elements in the scenario of 'array of arrays'.

Hope this resolves your query

2016-11-27 13:47
by Sayan


18

You can simply run:

[2,4,6,3,8].delete(3)
2014-10-17 07:30
by rilutham


18

A .delete_at(3) 3 here being the position.

2015-03-28 07:53
by Sawo Cliff


12

Here are some benchmarks:

require 'fruity'


class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8]

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 4096 times. Test will take about 2 seconds.
# >> soziev is similar to barlop
# >> barlop is faster than steve by 2x ± 1.0
# >> steve is faster than rodrigo by 4x ± 1.0
# >> rodrigo is similar to niels

And again with a bigger array containing lots of duplicates:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 1000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test 16 times. Test will take about 1 second.
# >> steve is faster than soziev by 30.000000000000004% ± 10.0%
# >> soziev is faster than barlop by 50.0% ± 10.0%
# >> barlop is faster than rodrigo by 3x ± 0.1
# >> rodrigo is similar to niels

And even bigger with more duplicates:

class Array          
  def rodrigo_except(*values)
    self - values
  end    

  def niels_except value
    value = value.kind_of?(Array) ? value : [value]
    self - value
  end
end

ARY = [2,4,6,3,8] * 100_000

compare do
  soziev  { a = ARY.dup; a.delete(3);               a }
  steve   { a = ARY.dup; a -= [3];                  a }
  barlop  { a = ARY.dup; a.delete_if{ |i| i == 3 }; a }
  rodrigo { a = ARY.dup; a.rodrigo_except(3);         }
  niels   { a = ARY.dup; a.niels_except(3);           }
end

# >> Running each test once. Test will take about 6 seconds.
# >> steve is similar to soziev
# >> soziev is faster than barlop by 2x ± 0.1
# >> barlop is faster than niels by 3x ± 1.0
# >> niels is similar to rodrigo
2016-03-28 23:43
by the Tin Man
So, what is the best of? : - Kirby 2016-04-11 08:54


6

I improved Niels's solution

class Array          
  def except(*values)
    self - values
  end    
end

Now you can use

[1, 2, 3, 4].except(3, 4) # return [1, 2]
[1, 2, 3, 4].except(4)    # return [1, 2, 3]
2015-11-20 14:06
by Rodrigo Mendonça
Your solution not working on irb console

2.2.1 :007 > [1, 2, 3, 4].except(3, 4) NoMethodError: undefined method except for [1, 2, 3, 4]:Array from (irb):7 from /usr/share/rvm/rubies/ruby-2.2.1/bin/irb:11:in <main> hgsongra 2016-07-06 03:44

To declare in IRB, you need to add the method to Array class Array; def except(*values); self - values; end; end - Mark Swardstrom 2017-03-02 17:53


3

You can also monkey patch it. I never understood why Ruby has an except method for Hash but not for Array:

class Array
  def except value
    value = value.kind_of(Array) ? value : [value]
    self - value
  end
end

Now you can do:

[1,3,7,"436",354,nil].except(354) #=> [1,3,7,"436",nil]

Or:

[1,3,7,"436",354,nil].except([354, 1]) #=> [3,7,"436",nil]
2015-07-28 12:15
by Niels Kristian
You don't need the value.kind_of(Array) test. Just use self - Array(value) - Sasgorilla 2017-03-07 15:02


2

So when you have multiple occurrences of 3 and you want only to delete the first occurrence of 3, you can simply do some thing as below.

arr = [2, 4, 6, 3, 8, 10, 3, 12]

arr.delete_at arr.index 3

#This will modify arr as [2, 4, 6, 8, 10, 3, 12] where first occurrence of 3 is deleted. Returns the element deleted. In this case => 3.
2016-09-14 03:15
by ashan priyadarshana


1

If you also want to make this deletion operation chainable, so you can delete some item and keep on chaining operations on the resulting array, use tap:

[2, 4, 6, 3, 8].tap { |ary| ary.delete(3) }.count #=> 4
2018-11-02 17:53
by dgilperez


0

Non-destructive removal of first occurrence:

a = [2, 4, 6, 3, 8]
n = a.index 3
a.take(n)+a.drop(n+1)
2018-08-18 02:07
by Lori
Ads