Issue #11815 has been updated by Martin Drst.


Cary Swoveland wrote:
> I spend a fair bit of time answering Ruby questions on SO and would have reached for this method on many occasions had it been available.

Then why don't you just provide pointers to those SO (StackOverflow?) questions, with explanations on how Array#difference would make things easier?



----------------------------------------
Feature #11815: Proposal for method `Array#difference`
https://bugs.ruby-lang.org/issues/11815#change-55550

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It issimilar to [Array#-](http://ruby-doc.org/core-2.2.0/Array.html#method-i-2D) but for each element of the (array) argument it removes only one matchingelement 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 asleast 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)
         dup.tap do |cpy|
           other.each do |e|
             ndx = cpy.index(e)
             cpy.delete_at(ndx) if ndx
            end
          end
        end
      end

Here are a few examples of its use:

*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]

*Determine if two words of the same size are anagrams of each other*

      w1, w2 = "stop", "pots"
      w1.chars.difference(w2.chars).empty?
        #=> true

*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.



-- 
https://bugs.ruby-lang.org/