如何在Ruby中高效地链接数组方法

ffvjumwh  于 2023-08-04  发布在  Ruby
关注(0)|答案(1)|浏览(138)

假设我有这个MWE代码:

# see below for full code - not important here
class RealEstate; attr_accessor :name; attr_accessor :living_space; attr_accessor :devices; def initialize(name, living_space, devices); @name = name; @living_space = living_space; @devices = devices; end; end

real_estates = [ RealEstate.new("ceiling", 30, [1]), # name, living_space, devices
                 RealEstate.new("1st floor", 50, [2,3]),
                 RealEstate.new("Ground floor", 70, [4,5]) ]

字符串

**(A)**现在我想使用数组方法,特别是pretzel colon,例如这个:

real_estates.map(&:living_space).inject(:+) # get the sum of all the available living space
real_estates.map(&:devices).map!(&:first) # get the first device of each floor

  • B数组被处理两次(或多次),这在一个巨大的现实世界的例子中有影响。但是,我可以在自己的(单个)循环中编写每个代码:
real_estate.inject(0) do |sum, o|
  sum + o.living_space
end
real_estate.map {|o| o.devices.first}


我真的更喜欢像块A中的语法,而不是B,但YMMV。我知道filter_mapflat_map,它们在某些情况下已经有所帮助,据称可以将性能提高4.5倍左右
特别是,当这些语句做了很多,并得到巨大的,(雏菊?)将它们链接在一起看起来像是一种使代码具有可读性的模式。参考:Method Chaining (Idiom):“火车残骸是干净的代码”
最后我的问题是如何防止出现中间结果(数组)和对同一个数组进行多次迭代?或者:如何有效地在数组方法上进行链接?
Rails在这里是适用的,但我认为也可以有一个纯Ruby的变体。我想象着这样的事情:

real_estates.map_inject(&:living_space,:+) # tbh you would need a combination for each of map, select, reject, each, etc.
real_estates.map(&:devices.first)
real_estates.map([&:devices,&:first])


我不仅使用map和inject,还使用filter、uniq、select、reject(所有可枚举)、flatten(数组)等,而且经常使用
整个MWE类代码:

class RealEstate
  attr_accessor :name
  attr_accessor :living_space
  attr_accessor :devices
  def initialize(name, living_space, devices)
    @name = name
    @living_space = living_space
    @devices = devices
  end
end

jpfvwuh4

jpfvwuh41#

我建议在你的类中添加一个helper方法:

class RealEstate
  attr_accessor :name, :living_space, :devices
  
  def initialize(name, living_space, devices)
    @name = name
    @living_space = living_space
    @devices = devices
  end

  def first_device 
    devices.first
  end
end

字符串
然后,您可以使用以下方法:

real_estates.sum(&:living_space) # using `sum` as Sergio Tulentsev suggested
real_estates.map(&:first_device) # using the helper method for readability

相关问题