我想知道一个数组中是否包含一个或多个特定的值。例如,如下所示:
[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
当然,"include?"方法只能检查一个值。是否有一种方法可以检查多个值?我想知道一个数组中是否包含一个或多个特定的值。例如,如下所示:
[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
当然,"include?"方法只能检查一个值。是否有一种方法可以检查多个值?>> [1,2,3,4,5,6] & [4,1]
=> [1, 4]
>> [1,2,3,4,5,6] & [7,9]
=> []
>>
any?
,如下所示:([1,2,3,4,5,6] & [4,1]).any? #=> true
。 - spyle这是一个集合操作。Set
是标准库中的一部分。
require 'set'
a = Set[1,2,3,4,5,6]
b = Set[4,1]
b.subset? a
#=> true
编辑:我支持Mark Thomas的备选解决方案,该解决方案使用了核心Set
类。
虽然我的解决方案更严格地回答了如何使用数组来解决这个问题,但sjsc可能会从审查自己的情况并探索使用集合的选项中受益。
有很多使用数组的有效原因(保持顺序,允许重复),对于这些原因,下面的解决方案仍然足够,但如果没有涉及到这些内容,则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
larger_array = [1,2,3,4,5,6]
smaller_array = [4,1]
smaller_array.all? {|smaller_array_item| larger_array.include?(smaller_array_item)}
根据Kurumi和Spyle的建议,这是我的测试:
([1,2,3,4,5,6] & [4,1]).any? #=> true
然而,.any? 会将任何对象转换为true。
([1,2,3,4,5,6] & [6,7]).any? #=> true
所以我认为这里可能有一个可行的方法:
([1,2,3,4,5,6] & [6,7]).length == [6,7].length #=> false
( bigger_array & smaller_array ).length == smaller_array.length
我喜欢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
[1,2,3,4,5,6].include?(4) and [1,2,3,4,5,6].include?(1)
有什么问题吗?
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
来源: http://rubydoc.info/stdlib/set/1.9.2/Set#subset%3F-instance_method
此方法用于检查给定的集合是否为另一个集合的子集。如果所提供的集合是另一个集合的子集,则返回true,否则返回false。@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
简单而最佳的方法:
([4,1] - [1,2,3,4,5,6]).empty? # => true
([4,1] - [4,1,6,2]).empty? # => true
([4,1] - [3,4,7]).empty? # => false