如何用Ruby实现按运动项目对人员哈希数组进行分组?
Ruby按运动项目分组人员的最简实现方式
初始数据
people = [ { "name" => "Mary", "sport" => "squash", "fruit" => "blackberry" }, { "name" => "Lauren", "sport" => "squash", "fruit" => "orange" }, { "name" => "Isla", "sport" => "weightlifting", "fruit" => "banana" }, { "name" => "Sam", "sport" => "cycling", "fruit" => "orange" }, { "name" => "Govind", "sport" => "squash", "fruit" => "banana" }, { "name" => "Awad", "sport" => "weightlifting", "fruit" => "kiwi" }, { "name" => "Will", "sport" => "cycling", "fruit" => "blackberry" } ] sport = { squash: [], weightlifting: [], cycling: [] }
需求
将上述人员按所选运动项目分组,最终得到:
sport = { squash: ["Mary", "Lauren", "Govind"], weightlifting: ["Isla", "Awad"], cycling: ["Sam", "Will"] }
我因哈希嵌套的情况感到困惑,目前尝试了以下代码但未成功:
sport[:squash].push(people.select {|k,v| k if v == "squash"})
最简实现方案
方案一:用group_by一步生成目标哈希
这是最符合Ruby风格的写法,通过两个内置方法直接完成分组和格式转换:
sport = people.group_by { |person| person["sport"].to_sym } .transform_values { |group| group.map { |p| p["name"] } }
group_by:按人员的sport字段分组,生成以运动项目为键、对应人员数组为值的哈希;to_sym:把字符串类型的运动项目转为符号,匹配目标哈希的键格式;transform_values:将每个分组里的人员哈希数组,转换为仅包含姓名的数组。
方案二:填充已定义的sport哈希
如果需要保留初始定义的sport哈希结构(比如已有其他默认配置),可以直接遍历人员数组填充:
people.each do |person| sport[person["sport"].to_sym] << person["name"] end
遍历每个人员,取出对应的运动项目(转成符号),将姓名追加到对应数组中即可。
原代码问题分析
你写的代码存在两个问题:
people.select的block参数错误:select遍历的是数组里的每个人员哈希,block参数应该是单个哈希对象(比如person),而非k,v;select返回的是符合条件的整个人员哈希数组,直接push会把整个数组作为一个元素塞进squash数组,无法得到预期的姓名列表。
内容的提问来源于stack exchange,提问作者wanderingnowhere
相关产品推荐
相关产品推荐

