[英]Finding an element in an array inside a hash
@members = {
approved: ["Jill"],
unapproved: ["Daniel"],
removed: ["John"],
banned: ["Daniel", "Jane"]
}
很简单:制作一个程序来跟踪会员资格。 在上面的哈希中,您可以看到四个成员资格状态键,每个键都有一个包含名称的数组。
我正在尝试创建一个find_member方法,该方法允许用户输入名称,然后在每个数组中搜索该名称,并告诉用户该名称位于哪个键中。
我对哈希不是很好,在尝试执行此操作时,我创建了一个混乱的循环,并且我想有一个非常简单的解决方案,但到目前为止我还没有找到。 有没有很简单的方法可以做到这一点?
我已经尝试了一些事情,但仍然没有过去的所有努力,但这是我最后遇到的最新情况,可能比我以前做的还要糟:
def find_member
puts "==Find Member=="
puts "Name: "
@name = gets.chomp
@members.each do |key|
key.values.each do |array|
array.each do |element|
if @name == element
puts "#{@name} found in #{key}"
else
puts "#{@name} not found in #{key}"
end
end
end
end
end
谢谢。
您可以在include?
使用此功能include?
方法。
@members = {
approved: ["Jill"],
unapproved: ["Daniel"],
removed: ["John"],
banned: ["Daniel", "Jane"]
}
def find_member_group(name)
@members.each { |group, names| return group if names.include?(name) }
nil
end
@name = 'Jane'
group_name = find_member_group(@name)
puts group_name ? "#{@name} found in #{group_name}." : "#{@name} not found."
# => Jane found in banned.
Hash#select是在此处使用的方法:
def find_member(name)
@members.select {|k,v| v.include? name }.keys
end
find_member("Jill") #=> [:approved]
find_member("Daniel") #=> [:unapproved, :banned]
find_member("John") #=> [:removed]
find_member("Jane") #=> [:banned]
说明:
select
顾名思义,仅选择并映射满足相应代码块中条件的那些元素。 该代码块不需要if
语句。 在代码块中,我们检查每个键值对 ,如果其值 包含 name
参数,则将选择该键值对并将其映射到最终输出。 最后,我们只对成员资格(即键)感兴趣,因此我们应用keys
方法以数组的形式获取这些成员资格。
最有效的方法是创建名称到键的一对多映射,并仅在@members
更改时更新该映射。
def find_member(name)
update_names_to_keys_if_necessary
@member_to_keys[name]
end
def update_names_to_keys_if_necessary
new_hashcode = @members.hash
return if @old_members.hashcode == new_hashcode
@member_to_keys = @members.each_with_object(Hash.new { |h,k| h[k] = [] }) { |(k,v),h|
v.each { |name| h[name] << k } }
@old_members_hashcode = new_hashcode
end
需要注意的是@old_members_hashcode
计算结果为nil
首次update_names_to_keys_if_necessary
被调用,所以@member_to_keys
将在那个时候被创建。
最初我们获得
@member_to_keys
#=> {"Jill"=>[:approved], "Daniel"=>[:unapproved, :banned],
# "John"=>[:removed], "Jane"=>[:banned]}
试试吧。
find_member("Jill")
#=> [:approved]
find_member("Daniel")
#=> [:unapproved, :banned]
find_member("John")
#=> [:removed]
find_member("Jane")
#=> [:banned]
find_member("Billy-Bob")
#=> []
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.