数组。包括?多重值

ruby 匿名 | 2020-02-27 02:22:50


[2, 6, 13, 99, 27].include?(2)
对于检查数组是否包含一个值很有效。但是如果我想检查一个数组是否包含多个值列表中的任何一个呢?有没有比执行
Array.include?(a) or Array.include?(b) or Array.include?(c) ...
更短的方法?





10 答案



您可以取两个数组的交集,看看它是否为空:
([2, 6, 13, 99, 27] & [2, 6]).any?

2020-02-27 02:23:07
匿名


你可以用可枚举的吗?方法,用代码块测试是否包含多个值。例如,要检查6或13:
[2, 6, 13, 99, 27].any? { |i| [6, 13].include? i }

2020-02-27 02:23:24
匿名


我感兴趣的是,这些不同的方法在性能上的比较,与其说是针对目前的问题,不如说是针对阵列与集合交集、阵列与集合的一般比较,不如说是针对阵列的
include?
include?
index
比较。我将编辑以添加建议的其他方法,如果您希望看到不同的基准参数,请告诉我。
我希望看到对这样的答案进行更多的基准测试。这不难也不费时,而且可以提供有用的见解。我发现大部分时间都在准备测试用例。注意,我已经将要测试的方法放在一个模块中,所以如果要对另一个方法进行基准测试,我只需要将该方法添加到模块中。
比较的方法
module Methods
require 'set'
def august(a,b) (a&b).any? end
def gnome_inc(a,b) a.any? { |i| b.include? i } end
def gnome_ndx(a,b) a.any? { |i| b.index i } end
def gnome_set(a,b) bs=b.to_set; a.any? { |i| bs.include? i } end
def vii_stud(a,b) as, bs = Set.new(a), Set.new(b); as.intersect?(bs) end
end
include Methods
@methods = Methods.instance_methods(false)
#=> [:august, :gnome_inc, :gnome_ndx, :gnome_set, :vii_stud]

测试数据
def test_data(n,m,c,r)
# n: nbr of elements in a
# m: nbr of elements in b
# c: nbr of elements common to a & b
# r: repetitions
r.times.each_with_object([]) { |_,a|
a << [n.times.to_a.shuffle, [*(n-c..n-c-1+m)].shuffle] }
end
d = test_data(10,4,2,2)
#=> [[[7, 8, 0, 3, 2, 9, 1, 6, 5, 4], [11, 10, 9, 8]],
# [[2, 6, 3, 4, 7, 8, 0, 9, 1, 5], [ 9, 11, 10, 8]]]
# Before `shuffle`, each of the two elements is:
#=> [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [8, 9, 10, 11]]
def compute(d, m)
d.each_with_object([]) { |(a,b),arr| arr << send(m, a, b) }
end
compute(d, :august)
#=> [true, true]

确认方法返回相同的值
d = test_data(1000,100,10,3)
r0 = compute(d, @methods.first)
puts @methods[1..-1].all? { |m| r0 == compute(d, m) }
#=> true

基准>Overlap of 20
n = 100000, m = 1000, overlap = 20, reps = 20
user system total real
august 0.100000 0.000000 0.100000 ( 0.108350)
gnome_inc 4.020000 0.000000 4.020000 ( 4.026290)
gnome_ndx 0.660000 0.010000 0.670000 ( 0.663001)
gnome_set 0.030000 0.000000 0.030000 ( 0.024606)
vii_stud 1.380000 0.050000 1.430000 ( 1.437340)

Overlap of 50
n = 100000, m = 1000, overlap = 50, reps = 20
user system total real
august 0.120000 0.000000 0.120000 ( 0.121278)
gnome_inc 2.170000 0.000000 2.170000 ( 2.236737)
gnome_ndx 0.310000 0.000000 0.310000 ( 0.308336)
gnome_set 0.020000 0.000000 0.020000 ( 0.015326)
vii_stud 1.220000 0.040000 1.260000 ( 1.259828)

Overlap of 100
n = 100000, m = 1000, overlap = 100, reps = 20
user system total real
august 0.110000 0.000000 0.110000 ( 0.112739)
gnome_inc 0.720000 0.000000 0.720000 ( 0.712265)
gnome_ndx 0.100000 0.000000 0.100000 ( 0.105420)
gnome_set 0.010000 0.000000 0.010000 ( 0.009398)
vii_stud 1.400000 0.050000 1.450000 ( 1.447110)

2020-02-27 02:23:42
匿名


简单方法:
([2, 6] - [2, 6, 13, 99, 27]).empty?

2020-02-27 02:23:55
匿名


require 'set'
master = Set.new [2, 6, 13, 99, 27]
data = Set.new [27, -3, -4]
#puts data.subset?(master) ? 'yes' : 'no' #per @meager comment
puts data.intersect?(master) ? 'yes' : 'no'
--output:--
yes

2020-02-27 02:24:07
匿名


在specs中,我最喜欢的方法之一是将数组和值转换为集合,并通过超集检查它?子集?方法。
例如:
[1, 2, 3, 4, 5].to_set.superset?([1, 2, 3].to_set) # true
[1, 2, 3].to_set.subset?([1, 2, 3, 4, 5].to_set) # true
[1, 2].to_set.subset?([1, 2].to_set) # true
[1, 2].to_set.superset?([1, 2].to_set) # true

但是,作为一个集合意味着集合中的所有值都是唯一的,因此可能并不总是合适的:
[1, 1, 1, 1, 1].to_set.subset? [1, 2].to_set       # true

每次我通常为此定义一个匹配器:
it 'returns array of "shown" proposals' do
expect(body_parsed.first.keys).to be_subset_of(hidden_prop_attrs)
end

在我看来,作为超集或子集的可读性要比执行以下操作强:
([1, 2, 3] & [1, 2]).any?

但是,将数组转换为集合的性能可能会降低。折衷

2020-02-27 02:24:16
匿名


这些工作-如果任何值匹配:
arr = [2, 6, 13, 99, 27]
if (arr - [2, 6]).size < arr.size
puts 'element match found'
else
puts 'element not found'
end

2020-02-27 02:24:23
匿名


我用这些扩展数组:
class Array
def include_exactly?(values)
self.include_all?(values) && (self.length == values.length)
end
def include_any?(values)
values.any? {|value| self.include?(value)}
end
def include_all?(values)
values.all? {|value| self.include?(value)}
end
def exclude_all?(values)
values.all? {|value| self.exclude?(value)}
end
end

2020-02-27 02:24:35
匿名


如果要检查阵列中是否存在两个元素。
2.4.1 :221 >   ([2, 6, 13, 99, 27] & [2, 6]).many?
=> true

2020-02-27 02:24:44
匿名


“[…]来自多个值的列表?”
这不管用吗?
arr.include?(2 || 3 || 4) 
#checks for 2 or 3 or 4.

2020-02-27 02:24:56
匿名


World is powered by solitude
备案号:湘ICP备19012068号