我有两个数组。一个存储字符串name
,另一个存储哈希值people
。我想过滤people
数组,找到一个与我的名字数组中的一个字符串完全匹配的哈希。因此,例如来自names
和 John Doe 的 John 将被视为匹配,因为两者都包含 John 。
names = ["John", "Jane"]
people = [{name: "John Doe"}, {name: "Bill Bradley"}]
我尝试使用select
方法匹配两者,但它返回一个空数组?
people.select{|person| person["name"] == names.any?}
答案 0 :(得分:0)
试试这个:
matches = people.select do |person|
!(names & person[:name].split(' ')).empty?
end
p matches #=> [{:name=>"John Doe"}]
基本上,您首先将哈希值与property[:name].split(' ')
分隔为单个词。结果将是['John', 'Doe']
之类的数组。然后,使用&amp ;;检查这个新创建的数组是否具有名称数组的任何公共元素。运营商。因此,你得到names & property[:name].split(' ')
。如果没有产生匹配,那么您将拥有一个不是您想要的空数组,因此!
(非)运算符。如果它更直观,你也可以这样做:
matches = people.reject do |person|
(names & person[:name].split(' ')).empty?
end
此外,如果您想获取散列本身而不是包含在数组中的散列(或散列,如果有多个结果),请将select
替换为detect
。< / p>
答案 1 :(得分:0)
这将是一种方式:
names = ["John", "Jane"]
people = [{name: "Johnny Jones"}, {name: "John Doe"}, {name: "Bill Bradley"}]
people.select { |h| hname = h[:name]; names.any? { |n| hname[/\b#{n}\b/i] } }
#=> [{:name=>"John Doe"}]
步骤:
enum = people.select
#=> #<Enumerator: [{:name=>"Johnny Jones"}, {:name=>"John Doe"},
# {:name=>"Bill Bradley"}]:select>
枚举数的第一个元素被传递到块中并分配给块变量h
:
h = enum.next
#=> {:name=>"Johnny Jones"}
接下来我创建一个临时变量,这样我们就不必为h[:name]
传入块中的每个元素提供enum
:
hname = h[:name]
#=> "Johnny Jones"
然后查看names
的任何元素是否与"Johnny Jones"
匹配:
names.any? { |n| hname[/\b#{n}\b/i] }
#=> ["John", "Jane"].any? { |n| "Johnny Jones"[/\b#{n}\b/i] }
#=> false
在最后一个表达式中,"John"
被传递到块中并分配给块变量n
。然后我们有:
"Johnny Jones"[/\bJohn\b/i]
#=> nil
第一个分词(\b
)要求"John"
前面紧跟非单词字符(或者是字符串的第一个字符);第二个单词中断要求"John"
后面紧跟一个非单词字符(或者是字符串中的最后一个字符)。因此,"John"
与"Johnny Jones"
不匹配。
names
的下一个(和最后一个)元素("Jane"
)然后传递到块中并分配给n
。"Johnny Jones"
不匹配{{ 1}},所以"Jane"
会返回any?
而可怜的约翰尼也不会被选中。
以类似的方式,John Doe被选中,Bill Bradley被送回家。