[#71931] [Ruby trunk - Feature #11786] [Open] [PATCH] micro-optimize case dispatch even harder — normalperson@...

Issue #11786 has been reported by Eric Wong.

9 messages 2015/12/08

[ruby-core:72140] [Ruby trunk - Feature #11815] Proposal for method `Array#difference`

From: duerst@...
Date: 2015-12-15 08:01:07 UTC
List: ruby-core #72140
Issue #11815 has been updated by Martin D=C3=BCrst.


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?) quest=
ions, 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:=20
----------------------------------------
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 =3D [1,2,3,4,3,2,2,4]
    b =3D [2,3,4,4,4]

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

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 instanc=
es of that element.=20

It could be implemented as follows:

     class Array
       def difference(other)
         dup.tap do |cpy|
           other.each do |e|
             ndx =3D 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 =3D [1,3,2,4,3,4]
      u =3D a.uniq #=3D> [1, 2, 3, 4]
      u - a.difference(u) #=3D> [1, 2]

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

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

*Identify a maximal number of 1-1 matches between the elements of two array=
s and return an array of all elements from both arrays that were not matche=
d*

      a =3D [1, 2, 4, 2, 1, 7, 4, 2, 9]=20
      b =3D [4, 7, 3, 2, 2, 7]=20
      a.difference(b).concat(b.difference(a))
        #=3D> [1, 1, 4, 2, 9, 3, 7]=20
=20=20
To remove elements from `a` starting at the end (rather the beginning) of `=
a`:

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

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

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



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

In This Thread

Prev Next