'delete_at' and 'slice' remove the item at the index and return that item. But 开发者_StackOverflow社区I don't really care about the removed item. I just want a new array with that item removed. Ruby's Array class doesn't seem to provide such a method.
Example would be:
a = ['a','b','c','d']
b = a.remove(2) #b => ['a','b','d']
Here 'remove' is a fictitious method that does what I want. I need the original array, so I want a new array return. I wonder if Ruby already has some built-in like this?
class Array
def remove(idx)
self[0...idx] + self[idx+1..-1]
end
end
a = ['a','b','c','d']
a.reject {|i| i == a[2] }
#=> ["a", "b", "d"]
irb(main):001:0> a = %w[ a b c d ]
#=> ["a", "b", "c", "d"]
irb(main):002:0> a.reject.with_index{ |o,i| i==2 }
#=> ["a", "b", "d"]
irb(main):003:0> a
#=> ["a", "b", "c", "d"]
Requires Ruby 1.9
With some monkey-patching:
irb(main):013:0> class Array
irb(main):014:1> def remove_at(i)
irb(main):015:2> self.dup.tap{ |clone| clone.delete_at(i) }
irb(main):016:2> end
irb(main):017:1> end
#=> nil
irb(main):018:0> a.remove_at(2)
#=> ["a", "b", "d"]
irb(main):019:0> a
#=> ["a", "b", "c", "d"]
it's quite hacky:
a = ['a','b','c','d']
b, = [a, a.delete_at(0)] # => ['b','c','d']
but it's faster(on my eeepc)
require 'benchmark'
n = 5000
Benchmark.bm do |x|
a = (1..5000).to_a
b = nil
x.report { n.times do; b, = [a, a.delete_at(0)]; end }
a = (1..5000).to_a
b = nil
x.report { n.times do; b = a.reject.with_index{ |o,i| i == 0 }; end }
end
user system total real
0.032000 0.000000 0.032000 ( 0.034002)
21.808000 0.156000 21.964000 ( 22.696298) OMG!
精彩评论