Ruby - 从哈希数组中提取特定键的值

6

我有一个哈希数组 @profiles,其中包含以下数据:

[{:user_id=>5, :full_name=>"Emily Spot"},{:user_id=>7, :full_name=>"Kevin Walls"}]

我想获取用户ID为7的全名。我正在尝试以下操作,但它抛出错误,表达式@profiles.find{|h| h[':user_id'] == current_user.id}为空。
name = @profiles.find{ |h| h[':user_id'] == current_user.id }[':full_name']

如果我使用select而不是find,那么会出现错误 - 没有将字符串隐式转换为整数。
我该如何搜索哈希数组?
更新:
在@Eric的回答之后,我重构了我的工作模型和视图操作:
  def full_names
    profile_arr||= []
    profile_arr = self.applications.pluck(:user_id)
    @profiles = Profile.where(:user_id => profile_arr).select([:user_id, :first_name, :last_name]).map {|e| {user_id: e.user_id, full_name: e.full_name} }
    @full_names = @profiles.each_with_object({}) do |profile, names|
      names[profile[:user_id]] = profile[:full_name]
    end
  end

In the view....,

p @current_job.full_names[current_user.id]
3个回答

7

@profiles 是一个包含哈希的数组,使用符号作为键,而你使用的是 String 对象。

因此,':user_id' 是一个字符串,而你需要符号 :user_id

@profiles.find{ |h| h[:user_id] == current_user.id } 

我想获取user_id == 7full_name

@profiles.find { |hash| hash[:user_id] == 7 }.fetch(:full_name, nil)

请注意,当在键:user_id中没有值为7的哈希时,我使用了Hash#fetch


哦,是的,我太傻了...那个引号是个错误。谢谢。好的,你的意思是安全操作符会在表达式的值为nil时绕过它? - Means
如果 @profiles.find { |hash| hash[:user_id] == 7 } 返回 nil,那么在没有安全导航符的情况下调用它的 name 将会引发异常,而有了安全导航符,它只会返回 nil - Andrey Deineko
@表示nil&.non_existing_method => nil - Andrey Deineko
抱歉,Andrey,但 '&.full_name' 抛出了一个错误:undefined method `full_name' for {:user_id=>5, :full_name=>"Emily Spot"}:Hash。只有当我将 [:full_name] 添加到 @profile.find 表达式中时,它才能正常工作。你有什么想法吗? - Means
@我的错,我编辑了答案,你是100%正确的,你不能在哈希上运行full_name,因为它没有实现该方法。 - Andrey Deineko

4

正如您所注意到的那样,提取user_id 7的名称并不是很方便。您可以稍微修改一下数据结构:

@profiles = [{:user_id=>5, :full_name=>"Emily Spot"},
             {:user_id=>7, :full_name=>"Kevin Walls"}]

@full_names = @profiles.each_with_object({}) do |profile, names|
  names[profile[:user_id]] = profile[:full_name]
end

p @full_names
# {5=>"Emily Spot", 7=>"Kevin Walls"}
p @full_names[7]
# "Kevin Walls"
p @full_names[6]
# nil

您并没有丢失任何信息,但是名称查找现在更快、更容易、更健壮。


1
Eric,这是一个非常好的答案...实际上对我来说完美地解决了问题,因为我现在已经将full_names移动到控制器中。我已经编辑了我的原始问题,展示了我之前的结构,并应用了你的建议。 - Means
@Means:好的,知道了。但是你可能应该在模型中放置这个逻辑。 - Eric Duminil
你能否建议一下,我的原始问题中的@profiles SQL查询-UPDATE部分,是否可以在不使用那个冗长的“select...map”组合的情况下进行改进/优化? - Means
@在您的编辑之后,很明显这个逻辑应该放到模型中。您应该考虑设置正确的关联。 - Andrey Deineko

1
建议创建一个新的哈希,以使事情更简单。
例如:
results = {}
profiles = [
  {user_id: 5, full_name: "Emily Spot"},
  {user_id: 7, full_name: "Kevin Walls"}
]

profiles.each do |details|
  results[details[:user_id]] = details[:full_name]
end

现在,结果将会有:
{5: "Emily Spot", 7: "Kevin Walls"}

因此,如果您需要获取用户ID为7的full_name,请执行以下操作:

results[7] # will give "Kevin Walls"

1
Michael,你并没有真正回答这个问题。你需要提供一个返回特定用户全名的解决方案。你的回答很接近,但我会将其投票否决,直到你有机会编辑或删除你的回答。 - WattsInABox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接