What's the best, most elegant/efficient way to test if an array contains any element from a second array?
如果一个数组包含来自第二个数组的任何元素,那么最好、最优雅/有效的方法是什么?
Two examples below, attempting to answer the question does 'foods' contain any element from 'cheeses':
下面举两个例子,试图回答这个问题:“食物”是否含有“奶酪”中的任何成分?
cheeses = %w(chedder stilton brie mozzarella feta haloumi)
foods = %w(pizza feta foods bread biscuits yoghurt bacon)
puts cheeses.collect{|c| foods.include?(c)}.include?(true)
puts (cheeses - foods).size < cheeses.size
4 个解决方案
#1
223
(cheeses & foods).empty?
It does the same, what posted injekt, but it's already compiled actions in a language.
它也做同样的事情,发布injekt,但它已经用一种语言编译了动作。
As Marc-André Lafortune said in comments, &
works in linear time while any?
+ include?
will be quadratic. For larger sets of data, linear time will be faster. For small data sets, any?
+ include?
may be faster as shown by Lee Jarvis' answer.
正如Marc-Andre Lafortune在评论中所言,&线性时间工作,还有吗?+包括什么?将二次。对于更大的数据集,线性时间将会更快。对于小数据集,有吗?+包括什么?李·贾维斯的回答可能会更快。
#2
20
How about Enumerable#any?
可列举的#任何怎么样?
>> cheeses = %w(chedder stilton brie mozzarella feta haloumi)
=> ["chedder", "stilton", "brie", "mozzarella", "feta", "haloumi"]
>> foods = %w(pizza feta foods bread biscuits yoghurt bacon)
=> ["pizza", "feta", "foods", "bread", "biscuits", "yoghurt", "bacon"]
>> foods.any? {|food| cheeses.include?(food) }
=> true
Benchmark script:
基准脚本:
require "benchmark"
N = 1_000_000
puts "ruby version: #{RUBY_VERSION}"
CHEESES = %w(chedder stilton brie mozzarella feta haloumi).freeze
FOODS = %w(pizza feta foods bread biscuits yoghurt bacon).freeze
Benchmark.bm(15) do |b|
b.report("&, empty?") { N.times { (FOODS & CHEESES).empty? } }
b.report("any?, include?") { N.times { FOODS.any? {|food| CHEESES.include?(food) } } }
end
Result:
结果:
ruby version: 2.1.9
user system total real
&, empty? 1.170000 0.000000 1.170000 ( 1.172507)
any?, include? 0.660000 0.000000 0.660000 ( 0.666015)
#3
19
You can check if the intersection is empty.
你可以检查十字路口是否空着。
cheeses = %w(chedder stilton brie mozzarella feta haloumi)
foods = %w(pizza feta foods bread biscuits yoghurt bacon)
foods & cheeses
=> ["feta"]
(foods & cheeses).empty?
=> false
#4
1
Set.new(cheeses).disjoint? Set.new(foods)
#1
223
(cheeses & foods).empty?
It does the same, what posted injekt, but it's already compiled actions in a language.
它也做同样的事情,发布injekt,但它已经用一种语言编译了动作。
As Marc-André Lafortune said in comments, &
works in linear time while any?
+ include?
will be quadratic. For larger sets of data, linear time will be faster. For small data sets, any?
+ include?
may be faster as shown by Lee Jarvis' answer.
正如Marc-Andre Lafortune在评论中所言,&线性时间工作,还有吗?+包括什么?将二次。对于更大的数据集,线性时间将会更快。对于小数据集,有吗?+包括什么?李·贾维斯的回答可能会更快。
#2
20
How about Enumerable#any?
可列举的#任何怎么样?
>> cheeses = %w(chedder stilton brie mozzarella feta haloumi)
=> ["chedder", "stilton", "brie", "mozzarella", "feta", "haloumi"]
>> foods = %w(pizza feta foods bread biscuits yoghurt bacon)
=> ["pizza", "feta", "foods", "bread", "biscuits", "yoghurt", "bacon"]
>> foods.any? {|food| cheeses.include?(food) }
=> true
Benchmark script:
基准脚本:
require "benchmark"
N = 1_000_000
puts "ruby version: #{RUBY_VERSION}"
CHEESES = %w(chedder stilton brie mozzarella feta haloumi).freeze
FOODS = %w(pizza feta foods bread biscuits yoghurt bacon).freeze
Benchmark.bm(15) do |b|
b.report("&, empty?") { N.times { (FOODS & CHEESES).empty? } }
b.report("any?, include?") { N.times { FOODS.any? {|food| CHEESES.include?(food) } } }
end
Result:
结果:
ruby version: 2.1.9
user system total real
&, empty? 1.170000 0.000000 1.170000 ( 1.172507)
any?, include? 0.660000 0.000000 0.660000 ( 0.666015)
#3
19
You can check if the intersection is empty.
你可以检查十字路口是否空着。
cheeses = %w(chedder stilton brie mozzarella feta haloumi)
foods = %w(pizza feta foods bread biscuits yoghurt bacon)
foods & cheeses
=> ["feta"]
(foods & cheeses).empty?
=> false
#4
1
Set.new(cheeses).disjoint? Set.new(foods)