2016-05-11 35 views
2

另一个阵列内匹配任何字符串考虑下面的代码:搜索哈希的数组,看是否在一个给定的哈希特定元素在Ruby中

cons = [ 
    { "FirstName" => "Bill", 
    "LastName" => "Wingy", 
    "Phone1" => "(800) 552-3209", 
    "Phone2" => "828 283-1134" 
    }, 
    { "FirstName" => "Ted", 
    "LastName" => "Dimble", 
    "Phone1" => "(823) 813-2834", 
    "Phone2" => "8823 232-2342" 
    } 
] 

pait_nums = [ "8282831134", "8282831132344" ] 

你如何搜索cons阵列返回哈希情形之一"Phone1".gsub(/\D/, '')"Phone2".gsub(/\D/, '')匹配pait_nums数组中的任何字符串?

+0

如果您经常这样做,您可以构建一个查找表,将查询表(将其剥离)映射到其各自的条目。 – Stefan

回答

0

让我们试试这个:

cons.select{ |con| pait_nums.include?(con['Phone1'].gsub(/\D/, '')) || pait_nums.include?(con['Phone2'].gsub(/\D/, '')) } 

或使其短

phone_keys = %w(Phone1 Phone2) 
cons.select{ |con| con.slice(*phone_keys).values.any?{ |val| pait_nums.include?(val.gsub(/\D/, '')) } } 
+0

此代码在“?”中为“8005523209”:String'在'?NoMethodError:undefined method'中引发异常。 – mudasobwa

+0

@mudasobwa刚更新了我的答案:D –

0

如果你正在使用的轨道,那么你可以使用红宝石present可以使用any?

cons.select{ |con| ([con['Phone1'].gsub(/\D/, ''), con['Phone2'].gsub(/\D/, '')] & pait_nums).present?} 

在红宝石你可以使用any?作为

cons.select{ |con| ([con['Phone1'].gsub(/\D/, ''), con['Phone2'].gsub(/\D/, '')] & pait_nums).any?} 
+0

在ruby中没有'Array#present?'这样的方法。 – mudasobwa

+0

@mudasobwa你检查完整的逻辑,我在那做了什么?我有两个数组的交集,如果它内部发现任何元素,那么它意味着给定的值存在于它内部。 –

+0

我不需要检查任何逻辑:你可以使用外部库的方法,而不需要任何注意。你的代码只会抛出'NoMethodError:未定义的方法'存在?'[...]:数组异常。 – mudasobwa

0
cons.select do |c| 
    c.select do |k, _| 
    k =~ /\APhone\d\z/      # select Phone* keys 
    end.values        # get values 
    .any? do |p| 
     pait_nums.include? p.gsub(/\D/, '') # get only matches 
    end 
end 

,或者对于键的任意集合来检查:

keys = %w|Phone1 Phone2| 
cons.select do |c| 
    c.select do |k, _| 
    keys.include? k      # select Phone* keys 
    end.values.any? do |p| 
    pait_nums.include? p.gsub(/\D/, '') # get only matches 
    end 
end 
2
phones = ["Phone1", "Phone2"] 
cons.find { |h| (h.values_at(*phones).map { |s| s.gsub(/\D/,"") } & pait_nums).any? } 
    #=> {"FirstName"=>"Bill", 
    # "LastName"=>"Wingy", 
    # "Phone1"=>"(800) 552-3209", 
    # "Phone2"=>"828 283-1134"} 

的步骤:

find最初通过的cons第一值到所述块并且设置块变量h至该值:

h = { "FirstName" => "Bill", 
     "LastName" => "Wingy", 
     "Phone1" => "(800) 552-3209", 
     "Phone2" => "828 283-1134" } 

以下块计算然后执行:

a = h.values_at(*phones) 
    #=> ["(800) 552-3209", "828 283-1134"] 
b = a.map { |s| s.gsub(/\D/,"") } 
    #=> ["8005523209", "8282831134"] 
c = b & pait_nums 
    #=> ["8005523209", "8282831134"] & ["8282831134", "8282831132344"] 
    #=> ["8282831134"] 
c.any? 
    #=> true 

c由于是truefind返回h。如果是cfalse,则第二个哈希将被发送到该块。

+1

不错的一个!你也可以在一个块中使用'any?',例如'cons.find {| h | h.values_at(*电话).ANY? {| s | pait_nums.include?(s.gsub(/ \ D /,''))}}' – Stefan