Ruby 如何调用数组中给定的不同方法
特别是在使用结构时,最好能够为数组中的每个元素调用不同的方法,如下所示:Ruby 如何调用数组中给定的不同方法,ruby,arrays,map,Ruby,Arrays,Map,特别是在使用结构时,最好能够为数组中的每个元素调用不同的方法,如下所示: array = %w{name 4 tag 0.343} array.convert(:to_s, :to_i, :to_sym, :to_f) # => ["name", 4, :tag, 0.343] 有没有简单的单行程序、ActiveSupport方法等可以轻松做到这一点?我提出的方法包括创建一个新的Struct子类,我称之为CastingStruct: class CastingStruct < St
array = %w{name 4 tag 0.343}
array.convert(:to_s, :to_i, :to_sym, :to_f)
# => ["name", 4, :tag, 0.343]
有没有简单的单行程序、ActiveSupport方法等可以轻松做到这一点?我提出的方法包括创建一个新的
Struct
子类,我称之为CastingStruct
:
class CastingStruct < Struct
def self.new(hash, &blk)
super(*hash.keys) do
define_method :initialize do |*args|
super *hash.values.map {|method| args.shift.public_send method }
end
class_eval(&blk) if blk
end
end
end
我会这样做:
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]
我加入了最后一行,显示convert
使args
保持不变,即使args
在convert
中被清空。这是因为args
在被传递到convert
之前被飞溅
根据@Arup的要求,我已经对他和我的解决方案进行了基准测试:
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)
Nit:The&:与对每个元素调用方法无关。。这就是使用&:结果的HoF函数。你能通过比较我的和你的来设定基准吗?我只是想看看破坏是否比构造快。使用splat也会使语法更直观,例如
array.convert:to_s,:to_i,:to_sym,:to_f
我在写这篇文章时使用了一些Arup Rakshit和Cary Swoveland的代码。
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)