Ruby 用值填充哈希的更好方法

Ruby 用值填充哈希的更好方法,ruby,Ruby,假设我有一个对象,它会响应一些方法。我想把它们收集成一堆,我总是写这样的剪报 class Person # ... def some_selected_attributes attrs = {} [:first_name, :last_name, :zip].each do |attr| attrs[attr] = self.__send__(attr) end attrs end end 我相信有一种更优雅的方法可以做到这一点 :wq

假设我有一个对象,它会响应一些方法。我想把它们收集成一堆,我总是写这样的剪报

class Person
  # ...

  def some_selected_attributes
    attrs = {}
    [:first_name, :last_name, :zip].each do |attr|
      attrs[attr] = self.__send__(attr)
    end
    attrs
  end
end
我相信有一种更优雅的方法可以做到这一点


:wq

由于只有三个属性,我认为没有理由不直接编写:

def some_selected_attributes
  {
    first_name: first_name,
    last_name: last_name,
    zip: zip
  }
end
p = Person.new
p.first_name  # => value of first_name
您也可以使用
inject

def some_selected_attributes
  [:first_name, :last_name, :zip].inject({}) do |hash, attr|
    hash[attr] = __send__ attr
    hash
  end
end
另一个选项,使用
Hash[]

def some_selected_attributes
  Hash[[:first_name, :last_name, :zip].map {|attr| [attr, __send__ attr] }]
end

如果你真的想要散列,LBg已经给了你一些很好的模式。但是,您可能需要考虑构造小结构对象而不是原始哈希。结构的行为类似于用于索引和枚举的哈希,但也有访问器方法,因此它们可以与send和dot表示法一起使用

class Person
  # ...
  SomeSelectedPersonAttrs = Struct.new :first_name, :last_name, :zip

  def some_selected_attributes
    SomeSelectedPersonAttrs[ * SomeSelectedPersonAttrs.members.map{|a| send a } ]
  end

end

pa = person.some_selected_attributes
pa.first_name    # => "Joe"
pa[:first_name]  # => "Joe"
pa['first_name'] # => "Joe"
p.zip = 12345    # sets zip to 12345
p[:zip] = 12345
p['zip'] = 12345

pa.values       # => ["Joe","Blow",12345]
pa.each_pair {|k,v| ... }

我认为有更好的方法来完成你想要做的事情。编写一个方法来返回类中已经存在的参数的散列没有多大意义。您可以使用attr\u accessor使实例变量或方法可访问:

class Person
  attr_accessor :first_name, :last_name, :zip

end
那么您就不需要some_selected_attributes()方法了。您可以直接访问变量或方法:

def some_selected_attributes
  {
    first_name: first_name,
    last_name: last_name,
    zip: zip
  }
end
p = Person.new
p.first_name  # => value of first_name
如果需要散列,可以创建它:

p = Person.new
hash = {:first_name => p.first_name, :last_name => p.last_name, :zip => p.zip }
我也不知道你为什么要构建这个散列。这似乎是一种更“面向对象”的方式来完成您试图做的任何事情(通过将整个对象作为参数传递)


我建议不要使用所选字段的散列,而是使用整个对象。

我还想提到inject。但即使我知道它的作用,我也会发现阅读起来很难。所以我经常想出
h={}。。。;返回h仅为可读性谢谢!第一个是不够的<代码>注入
方向正确,但很难读取。还有其他想法吗?你也可以用
每个带有对象的行来代替
注入
来摆脱只有
散列的行:
[:first\u name,:last\u name,:zip]。每个带有对象({})的行({attr,hash{hash[attr]=\uu send\uuu attr}