ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:72107] [Ruby trunk - Feature #11815] [Open] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
@ 2015-12-14  8:27 ` cary
  2015-12-14  9:38 ` [ruby-core:72111] [Ruby trunk - Feature #11815] " cary
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-14  8:27 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been reported by Cary Swoveland.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar to [Array#-](http://ruby-doc.org/core-2.2.0/Array.html#method-i-2D) but for each element of the (array) argument it remove 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` `1`, so the first `3-1 #=> 2` `2`'s in `a` have 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)
         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 non-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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72111] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
  2015-12-14  8:27 ` [ruby-core:72107] [Ruby trunk - Feature #11815] [Open] Proposal for method `Array#difference` cary
@ 2015-12-14  9:38 ` cary
  2015-12-15  4:33 ` [ruby-core:72132] " matz
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-14  9:38 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.


"*Identify an array's non-unique elements*" should be "*Identify an array's unique elements*".

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar to [Array#-](http://ruby-doc.org/core-2.2.0/Array.html#method-i-2D) but for each element of the (array) argument it remove 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` `1`, so the first `3-1 #=> 2` `2`'s in `a` have 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)
         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 non-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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72132] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
  2015-12-14  8:27 ` [ruby-core:72107] [Ruby trunk - Feature #11815] [Open] Proposal for method `Array#difference` cary
  2015-12-14  9:38 ` [ruby-core:72111] [Ruby trunk - Feature #11815] " cary
@ 2015-12-15  4:33 ` matz
  2015-12-15  5:15 ` [ruby-core:72135] " cary
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: matz @ 2015-12-15  4:33 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Yukihiro Matsumoto.


Is there any real world example?

Matz.


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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar to [Array#-](http://ruby-doc.org/core-2.2.0/Array.html#method-i-2D) but for each element of the (array) argument it remove 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` `1`, so the first `3-1 #=> 2` `2`'s in `a` have 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)
         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 non-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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72135] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2015-12-15  4:33 ` [ruby-core:72132] " matz
@ 2015-12-15  5:15 ` cary
  2015-12-15  6:56 ` [ruby-core:72138] " cary
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-15  5:15 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.


Matz, alas, I cannot offer one. You see, Ruby--coding generally--is just a hobby for me. 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. Perhaps readers with development experience (everybody but me?) could reflect on whether this method would have been useful in projects they've worked on.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar to [Array#-](http://ruby-doc.org/core-2.2.0/Array.html#method-i-2D) but for each element of the (array) argument it remove 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` `1`, so the first `3-1 #=> 2` `2`'s in `a` have 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)
         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 non-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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72138] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2015-12-15  5:15 ` [ruby-core:72135] " cary
@ 2015-12-15  6:56 ` cary
  2015-12-15  7:02 ` [ruby-core:72139] " cary
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-15  6:56 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.

Description updated

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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` `1`, so the first `3-1 #=> 2` `2`'s in `a` have 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72139] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2015-12-15  6:56 ` [ruby-core:72138] " cary
@ 2015-12-15  7:02 ` cary
  2015-12-15  8:01 ` [ruby-core:72140] " duerst
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-15  7:02 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.

Description updated

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72140] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2015-12-15  7:02 ` [ruby-core:72139] " cary
@ 2015-12-15  8:01 ` duerst
  2015-12-15  8:47 ` [ruby-core:72141] " cary
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: duerst @ 2015-12-15  8:01 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Martin Dürst.


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 is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72141] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2015-12-15  8:01 ` [ruby-core:72140] " duerst
@ 2015-12-15  8:47 ` cary
  2015-12-15 12:27 ` [ruby-core:72143] " 6ftdan
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-15  8:47 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.


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

Martin, see my [SO answer here](http://stackoverflow.com/questions/24987054/how-to-select-unique-elements), which contains links to a number of questions where I did use the method in my answer. 

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72143] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2015-12-15  8:47 ` [ruby-core:72141] " cary
@ 2015-12-15 12:27 ` 6ftdan
  2015-12-15 17:37 ` [ruby-core:72151] " cary
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: 6ftdan @ 2015-12-15 12:27 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Daniel P. Clark.


I like how your Array#difference method works well with duplicate entries.  I've only come across times where the difference of id references between two lists needed to be determined.  In my case it's

~~~ruby
a = [2, 4, 6, 8, 2, 4, 6, 8]
b = [1, 2, 3, 4, 1, 2, 3, 4]

# example
b - a
# => [1, 3, 1, 3]

b - a | a - b
# => [1, 3, 6, 8]
~~~

Like the example you first gave with added `| b - a` for getting two way evaluation on uniqueness.  If I wanted to get the same thing with Array#difference it looks the same as my example above.

~~~ruby
a = [2, 4, 6, 8, 2, 4, 6, 8]
b = [1, 2, 3, 4, 1, 2, 3, 4]

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

a.difference(b) | b.difference(a)
# => [1, 3, 6, 8]
~~~

So as to not cause confusion these are not the same as I will demonstrate with Cary Swoveland's input.

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

b.difference(a)
# => [4] 
b - a
# => []

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

As far as a real world use case for Array#difference: Service (A) exports all data to CSV files with a background worker. Service (B) exports to a database with a background worker.  Sometimes a background worker crashes.  Now to figure out what's missing we compare the difference between to two datasets.  *One flaw in my example is there is no determination in the position the new data needs to be entered to match the other.  In this case we would need to use something like Enumerator#with_index*

@Cary Swoveland; If I could make one recommendation on the implementation. I think it would be best to have it as an Enumerator so it can be performed with lazy evaluation.  That way when the difference is being compared we can perform operations along the way and save system resources.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72151] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2015-12-15 12:27 ` [ruby-core:72143] " 6ftdan
@ 2015-12-15 17:37 ` cary
  2015-12-15 17:52 ` [ruby-core:72154] " 6ftdan
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-15 17:37 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.


Daniel, thank you for your interesting observations. I too am fond of enumerators (`[true, false].cycle` being a fav), and I can see the advantages here. In my second example, for example, one could write `w1.chars.difference(w2.chars).none? #=> true`, avoiding the need for the construction of a temporary array.  On the other hand, if the method were often used in conjunction with other `Array` methods, tacking on `to_a` may become tiresome. The last line of my first example would become `u - a.difference(u).to_a`, my third example would be `a.difference(b).to_a.concat(b.difference(a).to_a)` and your example would be `a.difference(b).to_a | b.difference(a).to_a`. 

    

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72154] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (9 preceding siblings ...)
  2015-12-15 17:37 ` [ruby-core:72151] " cary
@ 2015-12-15 17:52 ` 6ftdan
  2015-12-18  3:48 ` [ruby-core:72235] " rp.beltran
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: 6ftdan @ 2015-12-15 17:52 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Daniel P. Clark.


Yeah.  Ideally, in my opinion, there would be an `Enumerator#difference` and an `Array#difference` as an alias to `Enumerator#difference.send :to_a`

One thing I really don't like about my Enumerator example is the duplication of an entire Array with `other.dup`.  I would like a more memory efficient way to iterate over "other" with one reference at a time and still have the destructive Array#delete_at methodology.  It would probably work best if the Array was implemented as a singly linked list and for every occurrence of delete we could create a new "single" reference with the pointer skipping that deleted item.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72235] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (10 preceding siblings ...)
  2015-12-15 17:52 ` [ruby-core:72154] " 6ftdan
@ 2015-12-18  3:48 ` rp.beltran
  2015-12-18 10:17 ` [ruby-core:72363] " duerst
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: rp.beltran @ 2015-12-18  3:48 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Ryan Beltran.


Yukihiro Matsumoto wrote:
> Is there any real world example?
> 
> Matz.

I think I have a pretty good example. I'm implementing a function in Ruby that finds triples in an array for use in a pokerbot (recognizes if a hand is a triple). I already defined a function to check for doubles (which is relatively trivial to implement by comparing to the array.uniq), but triples are a little bit harder. There are several ways I could be implement checking for triples, but a concise and efficient option would be to simply call:

`hasDouble(array.difference(array.uniq))` 

This works because if an array has a triple, then the difference between it and a set of it's unique values will have a double of the same value as the triple. This is much nicer than any methods I have come up with iteratively.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72363] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (11 preceding siblings ...)
  2015-12-18  3:48 ` [ruby-core:72235] " rp.beltran
@ 2015-12-18 10:17 ` duerst
  2015-12-19 19:22 ` [ruby-core:72392] " cary
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: duerst @ 2015-12-18 10:17 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Martin Dürst.


Ryan Beltran wrote:

> I think I have a pretty good example. I'm implementing a function in Ruby that finds triples in an array for use in a pokerbot (recognizes if a hand is a triple). I already defined a function to check for doubles (which is relatively trivial to implement by comparing the original array to array.uniq), but triples are a little bit harder. There are several ways I could implement checking for triples, but a concise and efficient option would be to simply call:
> 
> `getDoubles(array.difference(array.uniq))` 

> 
> ~~~ ruby
> doubles = array.difference(array.uniq)
> triples = doubles.difference(doubles)
> fours   = triples.difference(triples)
> ~~~

An even more straightforward way is to use group_by:

~~~ ruby
n_tuples = array.group_by {|e| e}.values.group_by(&:length)

doubles = n_tuples[2]
triples = n_tuples[3]
fours   = n_tuples[4]
# and so on
~~~ ruby

We need group_by two times because the first one groups items with the same value, and the second organizes these by numbers. As an example, if we start with [1,2,2,3,3,3,4,4,4,4,5,5,5,7,8,8] then after the first group_by, we have
{1=>[1], 2=>[2, 2], 3=>[3, 3, 3], 4=>[4, 4, 4, 4], 5=>[5, 5, 5], 7=>[7], 8=>[8, 8]}.
Of this, we only need the values: [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5], [7], [8, 8]].
Then we group by length and get:
{1=>[[1], [7]], 2=>[[2, 2], [8, 8]], 3=>[[3, 3, 3], [5, 5, 5]], 4=>[[4, 4, 4, 4]]}
To get an unique value (i.e. 3 instead of [3, 3, 3]), just use .map(&:first).

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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/

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:72392] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (12 preceding siblings ...)
  2015-12-18 10:17 ` [ruby-core:72363] " duerst
@ 2015-12-19 19:22 ` cary
  2016-08-19 22:43 ` [ruby-core:76988] [Ruby trunk Feature#11815] " cary
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2015-12-19 19:22 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.

Description updated

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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)
         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:

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



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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:76988] [Ruby trunk Feature#11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (13 preceding siblings ...)
  2015-12-19 19:22 ` [ruby-core:72392] " cary
@ 2016-08-19 22:43 ` cary
  2016-09-15 16:43 ` [ruby-core:77285] " cary
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2016-08-19 22:43 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.

Description updated

Implemented the method in a clearer and more efficient manner.

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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.

Note: I initially wrote the method 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




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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:77285] [Ruby trunk Feature#11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (14 preceding siblings ...)
  2016-08-19 22:43 ` [ruby-core:76988] [Ruby trunk Feature#11815] " cary
@ 2016-09-15 16:43 ` cary
  2018-09-29 14:14 ` [ruby-core:89215] " florian.ebeling
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 19+ messages in thread
From: cary @ 2016-09-15 16:43 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by Cary Swoveland.

Description updated

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

* Author: Cary Swoveland
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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](http://stackoverflow.com/questions/24987054/how-to-select-unique-elements).

Note: I initially wrote the method 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




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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:89215] [Ruby trunk Feature#11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (15 preceding siblings ...)
  2016-09-15 16:43 ` [ruby-core:77285] " cary
@ 2018-09-29 14:14 ` florian.ebeling
  2018-09-30 12:16 ` [ruby-core:89219] " florian.ebeling
  2018-10-05 20:04 ` [ruby-core:89290] " florian.ebeling
  18 siblings, 0 replies; 19+ messages in thread
From: florian.ebeling @ 2018-09-29 14:14 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by febeling (Florian Ebeling).


I could use this method for fixing this bug [1] in ActiveRecord. 

To me it looks like a valuable addition.

It's about replacing collection associations which can be partially persisted, with persisted records being handled differently as an optimization.  

1 https://github.com/rails/rails/issues/33942

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

* Author: CaryInVictoria (Cary Swoveland)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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](http://stackoverflow.com/questions/24987054/how-to-select-unique-elements).




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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:89219] [Ruby trunk Feature#11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (16 preceding siblings ...)
  2018-09-29 14:14 ` [ruby-core:89215] " florian.ebeling
@ 2018-09-30 12:16 ` florian.ebeling
  2018-10-05 20:04 ` [ruby-core:89290] " florian.ebeling
  18 siblings, 0 replies; 19+ messages in thread
From: florian.ebeling @ 2018-09-30 12:16 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by febeling (Florian Ebeling).


And analogously an method 'Array#intersection' would be valuable. Implementation could share most code.

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

* Author: CaryInVictoria (Cary Swoveland)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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](http://stackoverflow.com/questions/24987054/how-to-select-unique-elements).




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

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [ruby-core:89290] [Ruby trunk Feature#11815] Proposal for method `Array#difference`
       [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
                   ` (17 preceding siblings ...)
  2018-09-30 12:16 ` [ruby-core:89219] " florian.ebeling
@ 2018-10-05 20:04 ` florian.ebeling
  18 siblings, 0 replies; 19+ messages in thread
From: florian.ebeling @ 2018-10-05 20:04 UTC (permalink / raw)
  To: ruby-core

Issue #11815 has been updated by febeling (Florian Ebeling).


Now that `Array#difference` has in #14097 become yet another operator with set semantics this proposal should probably be closed.

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

* Author: CaryInVictoria (Cary Swoveland)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
I propose that a method `Array#difference` be added to the Ruby core. It is similar 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 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](http://stackoverflow.com/questions/24987054/how-to-select-unique-elements).




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

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2018-10-05 20:04 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-11815.20151214082709@ruby-lang.org>
2015-12-14  8:27 ` [ruby-core:72107] [Ruby trunk - Feature #11815] [Open] Proposal for method `Array#difference` cary
2015-12-14  9:38 ` [ruby-core:72111] [Ruby trunk - Feature #11815] " cary
2015-12-15  4:33 ` [ruby-core:72132] " matz
2015-12-15  5:15 ` [ruby-core:72135] " cary
2015-12-15  6:56 ` [ruby-core:72138] " cary
2015-12-15  7:02 ` [ruby-core:72139] " cary
2015-12-15  8:01 ` [ruby-core:72140] " duerst
2015-12-15  8:47 ` [ruby-core:72141] " cary
2015-12-15 12:27 ` [ruby-core:72143] " 6ftdan
2015-12-15 17:37 ` [ruby-core:72151] " cary
2015-12-15 17:52 ` [ruby-core:72154] " 6ftdan
2015-12-18  3:48 ` [ruby-core:72235] " rp.beltran
2015-12-18 10:17 ` [ruby-core:72363] " duerst
2015-12-19 19:22 ` [ruby-core:72392] " cary
2016-08-19 22:43 ` [ruby-core:76988] [Ruby trunk Feature#11815] " cary
2016-09-15 16:43 ` [ruby-core:77285] " cary
2018-09-29 14:14 ` [ruby-core:89215] " florian.ebeling
2018-09-30 12:16 ` [ruby-core:89219] " florian.ebeling
2018-10-05 20:04 ` [ruby-core:89290] " florian.ebeling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).