我正在查看数组中是否有一个或多个值。例如,像这样:
[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
当然,“包括?”方法只能检查一个值。有没有检查多个值的方法?
答案 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