2010-04-08 28 views
20

İki Ruby dizim var ve bunların hepsinde ortak değerler olup olmadığını görmem gerekiyor. Sadece bir dizideki her bir değerden geçebilir ve diğerinde?() Içerebilirim, ama eminim ki daha iyi bir yol var. Bu ne? (Dizilerin her ikisi de dizeleri tutar.)Bir Ruby dizisinin birkaç değerden birini içerip içermediğini nasıl kontrol edebilirim?

Teşekkürler.

+0

bunu ortak neler unsurlar duyar mısın deneyin? – Levi

+0

Hayır. Tek bilmek istediğim, eğer ikisinin de ortak bir unsuru varsa. – Colen

cevap

65

Set intersect onları:

> a1 = [ 'foo', 'bar' ] 
> a2 = [ 'bar', 'baz' ] 
> a1 & a2 
=> ["bar"] 
> !(a1 & a2).empty? # Returns true if there are any elements in common 
=> true 
+3

iyi, OP "kontrol etmek" istiyor, bu yüzden bir boole sonucu daha iyi bir uyum olacaktır:! (A1 & a2) .empty? – tokland

+4

(a1 & a2) ile giderdim. yerine (a1 & a2) .empty? – rilla

+1

@rilla 'any?' Bu durumda çalışır, ancak 'false' ve 'nil' değerleri ile uğraşırken değil:' [nil, false] .any? # => false '. – Stefan

6

ortak herhangi bir değer:

İşte
a1 & a2 

bir örnek? Eğer (tekrarlar da) ancak tam kesişme arıyorsanız burada yığın taşması zaten orada sorun daha karmaşıktır &

[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ] 

: How to return a Ruby array intersection with duplicate elements? (problem with bigrams in Dice Coefficient)

Veya hızlı bir snippet Eğer kesişim operatörünü kullanabilirsiniz hangi "real_intersection" tanımlar ve kavşak güzel görünüyor kullanarak şu testi

class ArrayIntersectionTests < Test::Unit::TestCase  
    def test_real_array_intersection 
    assert_equal [2], [2, 2, 2, 3, 7, 13, 49] & [2, 2, 2, 5, 11, 107] 
    assert_equal [2, 2, 2], [2, 2, 2, 3, 7, 13, 49].real_intersection([2, 2, 2, 5, 11, 107]) 
    assert_equal ['a', 'c'], ['a', 'b', 'a', 'c'] & ['a', 'c', 'a', 'd'] 
    assert_equal ['a', 'a', 'c'], ['a', 'b', 'a', 'c'].real_intersection(['a', 'c', 'a', 'd']) 
    end 
end 
3

doğrular, ancak verimsizdir. "Herhangi birini" kullanır mıyım? İlk dizide (böylece ikinci dizide öğelerden biri bulunduğunda yineleme durur). Ayrıca, ikinci dizide bir Set kullanarak üyelik kontrolleri hızlı yapacaktır. yani .:

a = [:a, :b, :c, :d] 
b = Set.new([:c, :d, :e, :f]) 
c = [:a, :b, :g, :h] 

# Do a and b have at least a common value? 
a.any? {|item| b.include? item} 
# true 

# Do c and b have at least a common value? 
c.any? {|item| b.include? item} 
#false 
+1

Kıyaslama, basit değerle nesne özniteliği karşılaştırmasına bağlı olarak (daha estetik olarak hoş) kesişim yönteminden 1.5-2x daha hızlı olduğunu gösterir. Yukarıdaki bir yorumda da belirtildiği gibi, "boş" yerine "any?" Kullanarak kesişimi ayarlayın, biraz değişti, ancak sonucu değiştirmedi. (Kesinlikle, ilk maçtaki performanstan ve beklediğimden beri beklediğim gibi.) –

0

bu

a1 = [ 'foo', 'bar' ] 
a2 = [ 'bar', 'baz' ] 
a1-a2 != a1 
true 
İlgili konular