比较数组并返回值,如果为true

时间:2013-06-18 07:52:13

标签: ruby-on-rails ruby ruby-on-rails-3

我有这两个数组

ArrayA = ["exampl@gmail.com", "example@techsolutions.net", "test@topgear.com"]
ArrayB = ["TopGear","Gmail", "Tech Solutions", "Google", "Facebook", "Exxon"]

现在我要做的是,如果ArrayA包含ArrayB中的任何值,它应该返回该值。我知道一个条目,我可以使用include?方法。我还想到将一个数组循环到另一个数组中,但这似乎没错,遇到了错误的循环次数。

那么我如何在这里比较两个数组并返回ArrayB的值,如果返回true?

例如,比较ArrayAArrayB时。数组中的输出可能看起来像

ArrayC = ["Gmail", "Tech Solutions", "TopGear"]

因为ArrayA中的电子邮件与ArrayB的内容相匹配。

希望它有意义。

注意:数组中的元素数量不限于上面示例中显示的内容。它可能是未来阵列中的更多元素。

感谢。任何帮助

4 个答案:

答案 0 :(得分:2)

ArrayA = ["exampl@gmail.com", "example@techsolutions.net", "test@topgear.com"]
ArrayB = ["TopGear","Gmail", "Tech Solutions", "Google", "Facebook", "Exxon"]

Hash[ArrayA.map{|i| [i,ArrayB.find_all{|j| i.include? j.downcase }]}]
#>> {"exampl@gmail.com"=>["Gmail"], "example@techsolutions.net"=>[], "test@topgear.com"=>["TopGear"]}

编辑:

ArrayA = ["exampl@gmail.com", "example@techsolutions.net", "test@topgear.com"]
ArrayB = ["TopGear","Gmail", "Tech Solutions", "Google", "Facebook", "Exxon"]

ArrayA.flat_map{|i| ArrayB.find_all{|j| i.include? j.delete(" ").downcase } }.uniq
#>> ["Gmail", "Tech Solutions", "TopGear"]

答案 1 :(得分:2)

找到交叉点的简单例子是:

ArrayA | ArrayB

根据您的示例找到匹配交集的天真算法是:

ArrayA.select do |e|
  ArrayB.each_with_object( e.downcase )
    .reduce( false ) { |a, (e, o)| a or o.include? e.downcase }
end
# => ["exampl@gmail.com", "test@topgear.com"]; Tech Solutions hase space in it

使用后缀树可以实现更好的算法,但是如果您的数组每个都有超过1000个元素,那么这只是有利的。这有点难以展示,因为很难找到迎合后缀树的Ruby宝石。但是出于演示目的,可以始终git clone git://github.com/respan/ukkonen-ruby.git,然后cd进入目录,然后在那里运行irb。算账:

require './ukkonen'
tree = SuffixTree.new ArrayA.join; nil
ArrayB.select { |e| tree.contains? e.downcase.delete ' ' }
#=>["TopGear", "Gmail", "Tech Solutions"]

请注意,虽然我希望为ArrayA构建一个通用后缀树,但这样的Ruby代码还没有发布,所以我使用{{{ 1}}。

答案 2 :(得分:1)

循环使用两个数组是唯一的方法。它不像存在一些可以在线性时间内比较两个数组的神奇函数。

看起来你想做的不仅仅是比较两个字符串。这并不容易。

答案 3 :(得分:1)

如果电子邮件检查是关键问题,我认为此代码将提供更好的性能(不需要嵌套循环),但这不是常见的解决方案。

Hash h = {}
ArrayB.each{|x| h[x.delete(" ").downcase] = 0}
ArrayA.each{|s|
    m = p(/.*@([^\.]+)\..*/).match(s);
    h[m[1]] += 1 if(m && h[m[1]]) 
}
ArrayC = [];
h.each{|k,v|  ArrayC << k if v > 0}