2010-04-08 173 views
20

我有兩個Ruby數組,我需要看他們是否有任何共同的值。我可以循環遍歷一個數組中的每個值,並在另一個數組中包含?(),但我確定有更好的方法。它是什麼? (陣列都保存字符串。)如何檢查Ruby數組是否包含多個值之一?

謝謝。

+0

你關心它的共同點是什麼元素呢? – Levi 2010-04-09 00:19:02

+0

不是。我想知道的是,如果兩者有共同點的話。 – Colen 2010-04-13 20:51:09

回答

65

Set intersect他們:

a1 & a2 

下面是一個例子:

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

好吧,OP想要「檢查」,所以布爾結果會更合適:!(a1&a2).empty? – tokland 2011-11-06 10:39:25

+4

我會去(a1&a2).any?而不是!(a1&a2).empty? – rilla 2014-08-27 09:10:38

+1

@rilla'any?'在這種情況下有效,但在處理'false'和'nil'值時不起作用:'[nil,false] .any? #=> false'。 – Stefan 2014-10-31 10:33:54

6

任何公共價值?如果您正在尋找但一個完整的路口(含重複)&

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

或快速snippet其定義「real_intersection」並驗證以下測試

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

使用交點看起來不錯,但效率不高。我會用「任何?」在第一個數組上(以便在第二個數組中找到其中一個元素時停止迭代)。此外,在第二個陣列上使用Set可以快速進行會員資格檢查。即:

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

根據簡單值與對象屬性比較,基準測試顯示此速度比(更美觀令人滿意的)集交集方法快1.5-2倍。正如上面的評論中所建議的那樣,使用'any?'而不是'empty?'設置交叉點,稍有不同,但並未改變結果。 (嚴格考慮表現,以及自第一場比賽以來任何'保釋'的預期。) – 2016-04-13 14:54:14

0

試試這個

a1 = [ 'foo', 'bar' ] 
a2 = [ 'bar', 'baz' ] 
a1-a2 != a1 
true 
相關問題