Determine if one array contains all elements of an

2020-06-03 01:29发布

I need to tell if an array contains all of the elements of another array with duplicates.

[1,2,3].contains_all? [1,2]   #=> true
[1,2,3].contains_all? [1,2,2] #=> false (this is where (a1-a2).empty? fails)
[2,1,2,3].contains_all? [1,2,2] #=> true

So the first array must contain as many or equal of the number of each unique element in the second array.

This question answers it for those using an array as a set, but I need to control for duplicates.

Update: Benchmarks

On Ruby 1.9.3p194

def bench
  puts Benchmark.measure {
    10000.times do
      [1,2,3].contains_all? [1,2]
      [1,2,3].contains_all? [1,2,2]
      [2,1,2,3].contains_all? [1,2,2]
    end
  }
end

Results in:

Rohit   0.100000   0.000000   0.100000 (  0.104486)
Chris   0.040000   0.000000   0.040000 (  0.040178)
Sergio  0.160000   0.020000   0.180000 (  0.173940)
sawa    0.030000   0.000000   0.030000 (  0.032393)

Update 2: Larger Arrays

@a1 = (1..10000).to_a
@a2 = (1..1000).to_a
@a3 = (1..2000).to_a

def bench
  puts Benchmark.measure {
    1000.times do
      @a1.contains_all? @a2
      @a1.contains_all? @a3
      @a3.contains_all? @a2
    end
  }
end

Results in:

Rohit    9.750000   0.410000  10.160000 ( 10.158182)
Chris   10.250000   0.180000  10.430000 ( 10.433797)
Sergio  14.570000   0.070000  14.640000 ( 14.637870)
sawa     3.460000   0.020000   3.480000 (  3.475513)

标签: ruby arrays
8条回答
做自己的国王
2楼-- · 2020-06-03 02:06
class Array
  def contains_all?(ary)
    ary.uniq.all? { |x| count(x) >= ary.count(x) }
  end
end

test

irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true

The following version is faster and shorter in code.

class Array
  def contains_all?(ary)
    ary.all? { |x| count(x) >= ary.count(x) }
  end
end
查看更多
Rolldiameter
3楼-- · 2020-06-03 02:15
class Array
  def contains_all? other
    other = other.dup
    each{|e| if i = other.index(e) then other.delete_at(i) end}
    other.empty?
  end
end
查看更多
登录 后发表回答