Especially when working with structs, it would be nice to be able to call a different method per each element in an array, something like this:
array = %w{name 4 tag 0.343}
array.convert(:to_s, :to_i, :to_sym, :to_f)
# => ["name", 4, :tag, 0.343]
Are there any simple one-liners, ActiveSupport methods, etc. to do this easily?
I would do this:
class Array
def convert(*args) map { |s| s.public_send args.shift } end
end
array = %w{name 4 tag 0.343}
args = [:to_s, :to_i, :to_sym, :to_f]
array.convert(*args)
#=> ["name", 4, :tag, 0.343]
args
#=> [:to_s, :to_i, :to_sym, :to_f]
I included the last line to show that convert leaves args unchanged, even though args is emptied within convert. That's because args was splatted before being passed to convert.
As per @Arup's request, I've benchmarked his and my solutions:
class Array
def sq_convert(*args)
zip(args).map { |string, meth| string.public_send(meth) }
end
def lf_convert(*args)
map { |s| s.public_send args.shift }
end
end
require 'benchmark'
n = 1_000_000
array = %w{name 4 tag 0.343}
args = [:to_s, :to_i, :to_sym, :to_f]
Benchmark.bmbm(15) do |x|
x.report("Arup's super-quick :") { n.times { array.sq_convert(*args) } }
x.report("Cary's lightning-fast:") { n.times { array.lf_convert(*args) } }
end
# Rehearsal ----------------------------------------------------------
# Arup's super-quick : 2.910000 0.000000 2.910000 ( 2.922525)
# Cary's lightning-fast: 2.150000 0.010000 2.160000 ( 2.155886)
# ------------------------------------------------- total: 5.070000sec
# user system total real
# Arup's super-quick : 2.780000 0.000000 2.780000 ( 2.784528)
# Cary's lightning-fast: 2.090000 0.010000 2.100000 ( 2.099337)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With