@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
感谢。
答案 0 :(得分:0)
您可以将此操作与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.
答案 1 :(得分:0)
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
方法以数组的形式获取这些成员。
答案 2 :(得分:0)
执行此操作的最有效方法是创建名称与键的一对多映射,并仅在@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")
#=> []