Dizi başka bir diziden herhangi bir değer içeriyor mu?


155

Bir dizinin ikinci bir diziden herhangi bir öğe içerip içermediğini test etmenin en etkili yolu nedir?

Aşağıdaki iki örnek, soruyu cevaplamaya çalışmak aşağıdaki foodsunsurları içermektedir cheeses:

cheeses = %w(chedder stilton brie mozzarella feta haloumi reblochon)
foods = %w(pizza feta foods bread biscuits yoghurt bacon)

puts cheeses.collect{|c| foods.include?(c)}.include?(true)

puts (cheeses - foods).size < cheeses.size

Yanıtlar:


268
(cheeses & foods).empty?

Marc-André Lafortune'un yorumlarda belirttiği gibi, &lineer zamanda çalışır, any?+ include?ikinci dereceden olacak. Daha büyük veri setleri için doğrusal zaman daha hızlı olacaktır. Küçük veri kümeleri için, any?+ include?, Lee Jarvis'in cevabında gösterildiği gibi daha hızlı olabilir - muhtemelen &başka bir çözüm bir boole döndürmek için basit bir iç içe döngü olarak çalışır ve yeni bir Dizi ayırır.


3
Bir dizinin başka bir diziden bir öğe içerip içermediğini kontrol ederken, (peynirler ve yiyecekler) yapmak daha anlamlı olmaz mı? eğer diziler aslında aynı elementlerden herhangi birini içeriyorsa, bu gerçek bir değer döndürür?
Ryan Francis

1
@RyanFrancis, dokümanlar: any?: blok hiç yanlış veya nil dışında bir değer verir, bu yöntem doğru döndürür. empty?: Kendinde öğe yoksa true değerini döndürür.
Nakilon

3
@Nakilon Ayrıca, cevabın neden (cheeses & foods).any?OP'nin sorusu olmadığı konusunda kafam karıştı : peynirlerde yiyecek varsa? Onun örneğinde, "feta" her ikisinde de, sonuç doğru olmalı, değil mi? Öyleyse neden .empty?kavşağı kontrol etmeliyiz?
SuckerForMayhem

@SuckerForMayhem, çünkü OP'nin sorusu "Varsa ... ?" Değil, sadece "Varsa?" " Are ... " belirtilmezse, "Varsa True? " Olduğu varsayılır ve [false, false, false]açık bir şekilde boş olmasa da, gibi dizi için False döndürür .
Nakilon

Etkin kayıt seviyesinde herhangi bir uygulama var mı?
Lee Chun Hoe

35

Nasıl hakkında Enumerable # herhangi?

>> 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

Karşılaştırma komut dosyası:

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

Sonuç:

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)

cheesesBir sete dönüşerek bunu geliştirebilirsiniz .
akuhn

1
Kendi kriterimi burada yakut 2.2.7 ve 2.3.4'te koştumany?, include? ve en hızlıydı
Jared

4
Bu kıyaslama belirtilen spesifik örnekle önyargılıdır ve daha genel bir durumda olması gerekmez. İki dizi arasında ortak unsur olmasaydı ne olurdu? Diziler her geçişte farklı bir sıradaysa ne olur? Her iki dizinin sonunda da beyaz görünürse ne olur? Marc-André'nin belirttiği gibi, set kavşağı doğrusal zamanda yürütülür, bu yüzden soruyu açıklığa kavuşturmak için kullanılan belirli bir örnek yerine genel durum için çok daha ölçeklenebilir olması mantıklıdır.
user2259664

22

Kavşağın boş olup olmadığını kontrol edebilirsiniz.

cheeses = %w(chedder stilton brie mozzarella feta haloumi)
foods = %w(pizza feta foods bread biscuits yoghurt bacon)
foods & cheeses
=> ["feta"] 
(foods & cheeses).empty?
=> false

1
Set.new(cheeses).disjoint? Set.new(foods)

Ayrıca (bilimsel olmayan) karşılaştırmamda, set ayrıklığı
Jared

1
Yorumlarınız için teşekkürler. Neden Set.new olmadığından emin değilim ama sadece düzenledim. Performans kriterlerinizi 2.4.1'de denedim. Benimki daha iyisini yaptı ama yine de daha fazla kelime içeren ayrık kümeler kullanarak en iyisi değildi. Sürümümü, özgeçmişiniz hakkında bir yoruma koydum. Ben de disjoint?özellikle "herhangi ?, dahil?" İle karşılaştırıldığında çok zarif olduğunu düşünüyorum . Orijinal soru hem zarif hem de verimli hakkında sorular sordu.
davidkovsky

.to_setyöntem burada yararlı olabilircheeses.to_set.disjoint?(foods.to_set)
itsnikolay

0
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) } } }  
  b.report("disjoint?") { N.times { FOODS.to_set.disjoint? CHEESES.to_set }}
end  
                      user     system      total        real
&, empty?         0.751068   0.000571   0.751639 (  0.752745)
any?, include?    0.408251   0.000133   0.408384 (  0.408438)
disjoint?        11.616006   0.014806  11.630812 ( 11.637300)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.