Project

General

Profile

Actions

Feature #11815

open

Proposal for method `Array#difference`

Added by CaryInVictoria (Cary Swoveland) over 8 years ago. Updated over 3 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:72107]

Description

I propose that a method Array#difference be added to the Ruby core. (Array#difference, which appears to be an alias of Array#-, was added to Ruby 2.6. Accordingly, I would propose that this method be named remove, but I will not make any changes here.) It is similar to Array#- but for each element of the (array) argument it removes only one matching element from the receiver. For example:

a = [1,2,3,4,3,2,2,4]
b = [2,3,4,4,4]

a - b #=> [1]
c = a.difference b #=> [1, 3, 2, 2] 

As you see, a contains three 2's and b contains 1, so the first 2 in a has been removed from a in constructing c. When b contains as least as many instances of an element as does a, c contains no instances of that element.

It could be implemented as follows:

class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

Here are a few examples of its use:

Determine if two arrays of the same size contain the same elements

  a = [2,1,4,2,5,3,3,1]
  b = [3,4,1,1,2,3,5,2] 
  a.difference(b).empty?
    #=> true

Identify an array's unique elements

  a = [1,3,2,4,3,4]
  u = a.uniq #=> [1, 2, 3, 4]
  u - a.difference(u) #=> [1, 2]

Identify a maximal number of 1-1 matches between the elements of two arrays and return an array of all elements from both arrays that were not matched

  a = [1, 2, 4, 2, 1, 7, 4, 2, 9] 
  b = [4, 7, 3, 2, 2, 7] 
  a.difference(b).concat(b.difference(a))
    #=> [1, 1, 4, 2, 9, 3, 7] 

To remove elements from a starting at the end (rather the beginning) of a:

a = [1,2,3,4,3,2,2,4]
b = [2,3,4,4,4]

a.reverse.difference(b).reverse #=> [1,2,3,2]

Array#difference! could be defined in the obvious way.

More information is in my answer to this SO question.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0