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

时间:2012-04-05 23:30:27

标签: 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

3 个答案:

答案 0 :(得分:2)

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

def some_selected_attributes
  {
    first_name: first_name,
    last_name: last_name,
    zip: zip
  }
end

您也可以使用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

答案 1 :(得分:1)

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

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| ... }

答案 2 :(得分:-1)

我认为有更好的方法来完成你想要做的事情。编写一个方法来返回已经在类中的参数的散列没有多大意义。您可以使用attr_accessor:

来访问实例变量或方法
class Person
  attr_accessor :first_name, :last_name, :zip

end

然后你不需要some_selected_attributes()方法。您可以直接访问变量或方法:

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 }

我不确定你为什么要构建这个哈希。看起来这是一种更“面向对象”的方式来完成你想要做的任何事情(通过将整个对象作为参数传递)。

我建议使用整个对象,而不是使用所选字段的哈希值。