如何检查数组的值是否包含一个或多个值?

时间:2011-02-04 02:11:04

标签: ruby arrays

我正在查看数组中是否有一个或多个值。例如,像这样:

[1,2,3,4,5,6].include?([4,1])  # => true
[4,1,6,2].include?([4,1])  # => true
[3,4,7].include?([4,1])  # => false

当然,“包括?”方法只能检查一个值。有没有检查多个值的方法?

12 个答案:

答案 0 :(得分:57)

>> [1,2,3,4,5,6] & [4,1]
=> [1, 4]
>> [1,2,3,4,5,6] & [7,9]
=> []
>>

答案 1 :(得分:26)

这是一个设定的操作。 Set位于标准库中。

require 'set'

a = Set[1,2,3,4,5,6]
b = Set[4,1]

b.subset? a
#=> true

答案 2 :(得分:16)

编辑:我支持Mark Thomas'使用核心Set class的备用解决方案。

虽然我的解决方案更严格地回答了如何使用数组执行此操作的问题,但sjsc可能会受益于查看自己的案例并探索使用集合的选项。

有很多有效的reasond使用数组(维护顺序,允许重复),以下仍然足够,但如果不涉及这些,sjsc可能实际上受益于使用Set而不是Array,并且范围,Mark的解决方案在语义上更优越。


我不知道有任何库方法可以做到这一点,但编写自己的函数并不难。

class Array
  def subset?(a)
    (self - a).length == 0
  end
end

我确信有更高效的方法可以实现这一目标,但这应该可以满足您的需求。

做数组交集工作,基本上是相同的。

class Array
  def subset?(a)
    (self & a).length == length
  end
end

此级别的优化不会有太大帮助,但您不想做的是多次开始比较数组:

class Array
  # don't do this
  def subset?(a)
    (self & a) == a
  end
end

答案 3 :(得分:6)

对@ Schwartzie方法的快速而肮脏的扩展:

larger_array = [1,2,3,4,5,6]
smaller_array = [4,1]
smaller_array.all? {|smaller_array_item| larger_array.include?(smaller_array_item)}

答案 4 :(得分:4)

根据kurumi和spyle的建议,这是我的测试:

  
    

([1,2,3,4,5,6]& [4,1])。任何? #=>真

  

然而,.any?将任何对象变为真

  
    

([1,2,3,4,5,6]& [6,7])。任何? #=>真

  

所以我认为这可能是一个有效的方法:

  
    

([1,2,3,4,5,6]& [6,7])。length == [6,7] .length#=>假

  

(greater_array& smaller_array)。length == smaller_array.length

答案 5 :(得分:3)

[1,2,3,4,5,6].include?(4) and [1,2,3,4,5,6].include?(1)出了什么问题?

答案 6 :(得分:2)

我的结论是减法方法通常很好,但实际的 Set 对象非常快,因为它们明显针对这种类型的计算进行了优化。

使用此脚本:https://gist.github.com/1996001

我得到了这些基准测试结果(在Ruby 1.9.2p290上):

SUBTRACTION
- subset
  0.180000   0.000000   0.180000 (  0.189767)
- partial subset
  0.170000   0.000000   0.170000 (  0.178700)
- non subset
  0.180000   0.000000   0.180000 (  0.177606)

INTERSECTION
- subset
  0.190000   0.000000   0.190000 (  0.194149)
- partial subset
  0.190000   0.000000   0.190000 (  0.191253)
- non subset
  0.190000   0.000000   0.190000 (  0.195798)

SET
- subset
  0.050000   0.000000   0.050000 (  0.048634)
- partial subset
  0.040000   0.000000   0.040000 (  0.045927)
- non subset
  0.050000   0.010000   0.060000 (  0.052925)

我认为这非常令人吃惊,特别是如果您查看来源:

# File 'lib/set.rb', line 204

def subset?(set)
  set.is_a?(Set) or raise ArgumentError, "value must be a set"
  return false if set.size < size
  all? { |o| set.include?(o) }
end

via:http://rubydoc.info/stdlib/set/1.9.2/Set#subset%3F-instance_method

答案 7 :(得分:2)

我喜欢kurumi的答案,但只想再扔一个:

>> set1 = [1,2,3,4,5,6]
[
    [0] 1,
    [1] 2,
    [2] 3,
    [3] 4,
    [4] 5,
    [5] 6
]
>> set2 = [4,1]
[
    [0] 4,
    [1] 1
]
>> set1.any?{ |num| set2.include?(num) }
true
>> set2 = [8,9]
[
    [0] 8,
    [1] 9
]
>> set1.any?{ |num| set2.include?(num) }
false

答案 8 :(得分:1)

@kurumi说得对,但我想我会补充一点,当我只想要一个数组的子集(通常是哈希键)时,我有时会使用这个小扩展:

class Hash
  # Usage { :a => 1, :b => 2, :c => 3}.except(:a) -> { :b => 2, :c => 3}
  def except(*keys)
    self.reject { |k,v|
      keys.include? k
    }
  end

  # Usage { :a => 1, :b => 2, :c => 3}.only(:a) -> {:a => 1}
  def only(*keys)
    self.dup.reject { |k,v|
      !keys.include? k
    }
  end
end

class Array
  def except(*values)
    self.reject { |v|
      values.include? v
    }
  end

  def only(*values)
    self.reject { |v|
      !values.include? v
    }
  end
end

答案 9 :(得分:0)

简单而好的方式:

([4,1] - [1,2,3,4,5,6])。空? #=&gt;真

([4,1] - [4,1,6,2])。空? #=&gt;真

([4,1] - [3,4,7])。空? #=&gt;假

答案 10 :(得分:0)

这将检查数组中是否存在元素:

students = ["jim", "bob", "sally"]
teachers = ["mrs. jones", "mrs. sharpe", "mrs. ray"]

puts "what's your name ?"
answer = gets.chomp

if answer.include?(students.to_s)
  puts "you are a student"

elsif
  puts "you are a teacher"

end

答案 11 :(得分:0)

要检查数组值是否包含单个或多个元素,可以在“ set”上转换数组,然后可以使用“ subset”?如下所示的方法。

    require "set"
    a = [1,2,3,4,5,6]
    b = [3,6]
    b.to_set.subset?a.to_set //true
    b= [3,7]
    b.to_set.subset?a.to_set //false