ruby Array.include? 多个值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25840356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 06:34:38  来源:igfitidea点击:

Array.include? multiple values

ruby

提问by Aaron Hooper

[2, 6, 13, 99, 27].include?(2)works well for checking if the array includes one value. But what if I want to check if an array includes any one from a list of multiple values? Is there a shorter way than doing Array.include?(a) or Array.include?(b) or Array.include?(c) ...?

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

回答by August

You could take the intersection of two arrays, and see if it's not empty:

你可以取两个数组的交集,看看它是否不为空:

([2, 6, 13, 99, 27] & [2, 6]).any?

回答by Todd A. Jacobs

You can use the Enumerable#any?method with a code block to test for inclusion of multiple values. For example, to check for either 6 or 13:

您可以使用Enumerable#any? 带有代码块的方法来测试是否包含多个值。例如,要检查 6 或 13:

[2, 6, 13, 99, 27].any? { |i| [6, 13].include? i }

回答by Cary Swoveland

I was interested in seeing how these various approach compared in performance, not so much for the problem at hand, but more for general comparisons of array vs set intersection, array vs set include?and include?vs indexfor arrays. I will edit to add other methods that are suggested, and let me know if you'd like to see different benchmark parameters.

我很感兴趣,看到这些不同的方法在性能上相比如何,与其说手头的问题,但更多的VS组阵列VS交集,阵列的一般性的比较include?include?VSindex数组。我将编辑添加建议的其他方法,如果您想查看不同的基准参数,请告诉我。

I for one would like to see more benchmarking of SO answers done. It's not difficult or time-consuming, and it can provide useful insights. I find most of the time is preparing the test cases. Notice I've put the methods to be tested in a module, so if another method is to be benchmarked, I need only add that method to the module.

我希望看到更多关于 SO 答案的基准测试。这并不困难或耗时,并且可以提供有用的见解。我发现大部分时间都是在准备测试用例。请注意,我已将要测试的方法放在一个模块中,因此如果要对另一种方法进行基准测试,我只需将该方法添加到模块中。

Methods compared

方法比较

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]

Test data

测试数据

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]

Confirm methods return the same values

确认方法返回相同的值

d = test_data(1000,100,10,3)
r0 = compute(d, @methods.first) 
puts @methods[1..-1].all? { |m| r0 == compute(d, m) }
  #=> true

Benchmark code

基准代码

require 'benchmark'

@indent = methods.map { |m| m.to_s.size }.max

def test(n, m, c, r, msg)
  puts "\n#{msg}"
  puts "n = #{n}, m = #{m}, overlap = #{c}, reps = #{r}"
  d = test_data(n, m, c, r)
  Benchmark.bm(@indent) do |bm|
    @methods.each do |m|
      bm.report m.to_s do
        compute(d, m)
      end
    end
  end
end

Tests

测试

n = 100_000
m = 1000
test(n, m,    0,  1, "Zero overlap")
test(n, m, 1000,  1, "Complete overlap")
test(n, m,    1, 20, "Overlap of 1")
test(n, m,    5, 20, "Overlap of 5")
test(n, m,   10, 20, "Overlap of 10")
test(n, m,   20, 20, "Overlap of 20")
test(n, m,   50, 20, "Overlap of 50")
test(n, m,  100, 20, "Overlap of 100")

Zero overlap
n = 100000, m = 1000, overlap = 0, reps = 1
                                 user     system      total        real
august                       0.010000   0.000000   0.010000 (  0.005491)
gnome_inc                    4.480000   0.010000   4.490000 (  4.500531)
gnome_ndx                    0.810000   0.000000   0.810000 (  0.822412)
gnome_set                    0.030000   0.000000   0.030000 (  0.031668)
vii_stud                     0.080000   0.010000   0.090000 (  0.084283)

Complete overlap
n = 100000, m = 1000, overlap = 1000, reps = 1
                                 user     system      total        real
august                       0.000000   0.000000   0.000000 (  0.005841)
gnome_inc                    0.010000   0.000000   0.010000 (  0.002521)
gnome_ndx                    0.000000   0.000000   0.000000 (  0.000350)
gnome_set                    0.000000   0.000000   0.000000 (  0.000655)
vii_stud                     0.090000   0.000000   0.090000 (  0.097850)

Overlap of 1
n = 100000, m = 1000, overlap = 1, reps = 20
                                 user     system      total        real
august                       0.110000   0.000000   0.110000 (  0.116276)
gnome_inc                   61.790000   0.100000  61.890000 ( 62.058320)
gnome_ndx                   10.100000   0.020000  10.120000 ( 10.144649)
gnome_set                    0.360000   0.000000   0.360000 (  0.357878)
vii_stud                     1.450000   0.050000   1.500000 (  1.501705)

Overlap of 5
n = 100000, m = 1000, overlap = 5, reps = 20
                                 user     system      total        real
august                       0.110000   0.000000   0.110000 (  0.113747)
gnome_inc                   16.550000   0.050000  16.600000 ( 16.728505)
gnome_ndx                    2.470000   0.000000   2.470000 (  2.475111)
gnome_set                    0.100000   0.000000   0.100000 (  0.099874)
vii_stud                     1.630000   0.060000   1.690000 (  1.703650)

Overlap of 10
n = 100000, m = 1000, overlap = 10, reps = 20
                                 user     system      total        real
august                       0.110000   0.000000   0.110000 (  0.112674)
gnome_inc                   10.090000   0.020000  10.110000 ( 10.131339)
gnome_ndx                    1.470000   0.000000   1.470000 (  1.478400)
gnome_set                    0.060000   0.000000   0.060000 (  0.062762)
vii_stud                     1.430000   0.050000   1.480000 (  1.476961)

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)

回答by Naveen Kumar

Simple way:

简单的方法:

([2, 6] - [2, 6, 13, 99, 27]).empty?

回答by 7stud

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

回答by Dyaniyal Wilson

If you want to check two elements are present in the array.

如果要检查数组中是否存在两个元素。

2.4.1 :221 >   ([2, 6, 13, 99, 27] & [2, 6]).many?
 => true

回答by Danny Ocean

One of my favourite methods of doing that in specs is to convert an array and a value to the Set and check it via #superset?& #subset?methods.

我最喜欢在规范中这样做的方法之一是将数组和值转换为 Set 并通过#superset 进行检查& #子集?方法。

For example:

例如:

[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

However, being a set means that all values in a collection are unique, so it may not always be appropriate:

但是,作为一个集合意味着集合中的所有值都是唯一的,因此它可能并不总是合适的:

[1, 1, 1, 1, 1].to_set.subset? [1, 2].to_set       # true

To avoid calling .to_setevery time I usually define a matcher for that:

为了避免.to_set每次我通常为此定义匹配器时都调用:

it 'returns array of "shown" proposals' do
  expect(body_parsed.first.keys).to be_subset_of(hidden_prop_attrs)
end

In my humble opinion, being a superset or a subset is just more readable than doing:

在我看来,作为超集或子集比做更易读:

([1, 2, 3] & [1, 2]).any?

However, converting an array to a set may be a less performant. Tradeoffs ˉ\_(ツ)_/ˉ

但是,将数组转换为集合可能会降低性能。权衡 ˉ\_(ツ)_/ˉ

回答by Yarin

I extend Array with these:

我用这些扩展数组:

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

回答by Lalu

This works - if any of the value matches:

这有效 - 如果任何值匹配:

arr = [2, 6, 13, 99, 27]
if (arr - [2, 6]).size < arr.size
 puts 'element match found'
else
 puts 'element not found'
end