【问题标题】:Ruby - Extract value of a particular key from array of hashesRuby - 从哈希数组中提取特定键的值
【发布时间】:2017-06-21 21:09:12
【问题描述】:

我有一个哈希数组 - @profiles 的数据如下:

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

我想获取 user_id = 7 的全名?我正在执行以下操作:但它会抛出一个错误,即表达式 @profiles.find{|h| h[':user_id'] == current_user.id} 为 nil。

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

如果我使用 select 而不是 find 则错误是 - 没有将 String 隐式转换为 Integer。

如何搜索哈希数组?

更新:

在@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

在视图中......,

p @current_job.full_names[current_user.id]

【问题讨论】:

    标签: ruby-on-rails arrays ruby hash


    【解决方案1】:

    @profiles 是一个哈希数组,以符号为键,而您使用的是 String 对象。

    所以':user_id' 是一个字符串,而你想要符号::user_id:

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

    我想得到full_name,比如user_id == 7

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

    注意,我使用Hash#fetch 表示,当键:user_id 处没有值为7 的哈希时。

    【讨论】:

    • 哦,是的,我真傻……那句话是个错误。谢谢。好的,你的意思是如果表达式的值为 nil,安全运算符将绕过?
    • @意味着是的,所以如果@profiles.find { |hash| hash[:user_id] == 7 } 返回nil,没有安全导航调用name 将引发异常,而使用安全导航它只会返回nil
    • @Means nil&.non_existing_method => nil
    • 抱歉,Andrey,但 '&.full_name' 引发了错误:{:user_id=>5, :full_name=>"Emily Spot"}:Hash 的未定义方法 `full_name'。只有当我将 [:full_name] 附加到该 @profile.find 表达式时,它才有效。有什么想法吗?
    • @意味着我的错,我编辑了答案,你是 100% 正确的,你不能在哈希上运行 full_name,因为它没有实现那个方法。
    【解决方案2】:

    正如您所注意到的,提取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
    

    您没有丢失任何信息,但名称查找现在更快、更轻松、更健壮。

    【讨论】:

    • Eric,这是一个开箱即用的答案....实际上对我来说非常有用,因为我现在已将 full_names 移至控制器。我已经编辑了我的原始问题,以展示我之前如何构建它,现在应用您的输入。
    • @Means:很高兴知道。不过,您可能应该将此逻辑放入模型中。
    • 您能否建议我的原始问题 -UPDATE 部分中的 @profiles SQL 查询是否可以在没有较长的 'select...map' 组合的情况下进行改进/优化?
    • @Means 编辑后很明显,这个逻辑应该进入模型。您应该考虑建立适当的关联。
    【解决方案3】:

    建议,创建一个可以让事情变得更简单的新哈希

    例如:

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

    因此,如果您需要获取 user_id = 7 的全名,只需执行以下操作:

    results[7] # will give "Kevin Walls"
    

    【讨论】:

    • 迈克尔,你没有真正回答这个问题。您需要提供一个返回特定用户全名的解决方案。你的答案很接近,但在你有机会编辑或删除你的答案之前,我会投反对票。
    猜你喜欢
    • 1970-01-01
    • 2019-11-21
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 2015-03-16
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多