【问题标题】:How can I check if a Ruby array includes one of several values?如何检查 Ruby 数组是否包含多个值之一?
【发布时间】:2010-04-08 22:30:41
【问题描述】:

我有两个 Ruby 数组,我需要看看它们是否有任何共同的值。我可以遍历一个数组中的每个值并在另一个数组中包含?(),但我确信有更好的方法。它是什么? (数组都包含字符串。)

谢谢。

【问题讨论】:

  • 你关心它有什么共同点吗?
  • 不。我只想知道两者是否有任何共同点。

标签: ruby string arrays intersect


【解决方案1】:

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

【讨论】:

  • 好吧,OP 想要“检查”,所以布尔结果会更合适:!(a1 & a2).empty?
  • 我会选择 (a1 & a2).any?而不是 !(a1 & a2).empty?
  • @rilla any? 在这种情况下有效,但在处理 falsenil 值时无效:[nil, false].any? #=> false
  • 有没有更简洁的方法来做!(a1 & a2).empty?
  • @DavidWest 是的,(a1 & a2).present?.
【解决方案2】:

有什么共同点吗?您可以使用交集运算符:&

[ 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.5-2 倍,具体取决于简单值与对象属性的比较。正如上面评论中所建议的那样,使用any? 而不是empty? 设置交叉点略有不同,但并没有改变结果。 (严格考虑性能,正如预期的那样,any? 在第一场比赛中保释。)
    【解决方案4】:

    数组#intersect? (红宝石 3​​.1+)

    从 Ruby 3.1 开始,有一个新的Array#intersect? 方法, 它检查两个数组是否至少有一个共同元素。

    这是一个例子:

    a = [1, 2, 3]
    b = [3, 4, 5]
    c = [7, 8, 9]
    
    # 3 is the common element
    a.intersect?(b)
    # => true
    
    # No common elements
    a.intersect?(c)
    # => false
    

    此外,Array#intersect? 可以比替代方案快得多,因为它避免创建中间数组,一旦找到公共元素就返回 true,它是在 C 中实现的。

    来源:

    【讨论】:

      【解决方案5】:

      试试这个

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-06
        • 2016-10-02
        • 1970-01-01
        • 1970-01-01
        • 2017-10-17
        • 2017-05-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多