Determine if one array contains all elements of another array

前端 未结 8 1883
闹比i
闹比i 2021-02-07 12:05

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         


        
相关标签:
8条回答
  • 2021-02-07 12:18
    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
    
    0 讨论(0)
  • 2021-02-07 12:21

    Counting the number of occurrences and comparing them seems to be the obvious way to go.

    class Array
       def contains_all? arr
           h = self.inject(Hash.new(0)) {|h, i| h[i] += 1; h}
           arr.each do |i|
               return false unless h.has_key?(i)
               return false if h[i] == 0
               h[i] -= 1
           end
           true
       end
    end
    
    0 讨论(0)
  • 2021-02-07 12:22

    Answering with my own implementation, but definitely want to see if someone can come up with a more efficient way. (I won't accept my own answer)

    class Array
      def contains_all?(a2)
        a2.inject(self.dup) do |copy, el|
          if copy.include? el
            index = copy.index el
            copy.delete_at index
          else
            return false
          end
          copy
        end
        true
      end
    end
    

    And the tests:

    1.9.3p194 :016 > [1,2,3].contains_all? [1,2]   #=> true
     => true 
    1.9.3p194 :017 > [1,2,3].contains_all? [1,2,2] #=> false (this is where (a1-a2).empty? fails)
     => false 
    1.9.3p194 :018 > [2,1,2,3].contains_all? [1,2,2] #=> true
     => true 
    
    0 讨论(0)
  • 2021-02-07 12:26
    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
    
    0 讨论(0)
  • 2021-02-07 12:28

    If you can't find a method, you can build one using ruby's include? method.

    Official documentation: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-include-3F

    Usage:

    array = [1, 2, 3, 4]
    array.include? 3       #=> true
    

    Then, you can do a loop:

    def array_includes_all?( array, comparision_array )
      contains = true
      for i in comparision_array do
        unless array.include? i
          contains = false
        end
      end
      return contains
    end
    
    array_includes_all?( [1,2,3,2], [1,2,2] )    #=> true
    
    0 讨论(0)
  • 2021-02-07 12:33

    This solution will only iterate through both lists once, and hence run in linear time. It might however be too much overhead if the lists are expected to be very small.

      class Array
        def contains_all?(other)
          return false if other.size > size
          elem_counts = other.each_with_object(Hash.new(0)) { |elem,hash| hash[elem] += 1 }
          each do |elem|
            elem_counts.delete(elem) if (elem_counts[elem] -= 1) <= 0
            return true if elem_counts.empty?
          end
          false
        end
      end
    
    0 讨论(0)
提交回复
热议问题