在哈希中查找数组中的元素

时间:2016-07-13 15:09:39

标签: arrays ruby 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

感谢。

3 个答案:

答案 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")
  #=> []