From: Joseph Jones Date: 2015-12-17T21:07:28-07:00 Subject: [ruby-core:72308] [Ruby trunk - Feature #11815] [Open] Proposal for method `Array#difference` --56738680_1eba5d23_16c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Joseph Jones liked your message with Boxer. On December 14, 2015 at 01:27= :10 MST, cary=40swoveland.com wrote:Issue =2311815 has been reported by C= ary Swoveland.----------------------------------------=46eature =2311815:= Proposal for method =60Array=23difference=60https://bugs.ruby-lang.org/i= ssues/11815* Author: Cary Swoveland* Status: Open* Priority: Normal* Assi= gnee: ----------------------------------------I propose that a method =60= Array=23difference=60 be added to the Ruby core. It is similar to =5BArra= y=23-=5D(http://ruby-doc.org/core-2.2.0/Array.html=23method-i-2D) but for= each element of the (array) argument it remove only one matching element= from the receiver. =46or example: a =3D =5B1,2,3,4,3,2,2,4=5D b =3D =5B2= ,3,4,4,4=5D a - b =23=3D> =5B1=5D c =3D a.difference b =23=3D> =5B1, 3, 2= , 2=5D As you see, =60a=60 contains three =602=60's and =60b=60 =601=60, = so the first =603-1 =23=3D> 2=60 =602=60's in =60a=60 have been removed f= rom =60a=60 in constructing =60c=60. When =60b=60 contains as least as ma= ny instances of an element as does =60a=60, =60c=60 contains no instances= of that element. It could be implemented as follows: class Array def dif= ference(other) dup.tap do =7Ccpy=7C other.each do =7Ce=7C ndx =3D cpy.ind= ex(e) cpy.delete=5Fat(ndx) if ndx end end end endHere are a few examples = of its use:*Identify an array's non-unique elements* a =3D =5B1,3,2,4,3,4= =5D u =3D a.uniq =23=3D> =5B1, 2, 3, 4=5D u - a.difference(u) =23=3D> =5B= 1, 2=5D*Determine if two words of the same size are anagrams of each othe= r* w1, w2 =3D =22stop=22, =22pots=22 w1.chars.difference(w2.chars).empty=3F= =23=3D> true*Identify a maximal number of 1-1 matches between the elemen= ts of two arrays and return an array of all elements from both arrays tha= t were not matched* a =3D =5B1, 2, 4, 2, 1, 7, 4, 2, 9=5D b =3D =5B4, 7,= 3, 2, 2, 7=5D a.difference(b).concat(b.difference(a)) =23 =3D> =5B1, 1,= 4, 2, 9, 3, 7=5D To remove elements from =60a=60 starting at the end (r= ather the beginning) of =60a=60: a =3D =5B1,2,3,4,3,2,2,4=5D b =3D =5B2,3= ,4,4,4=5D a.reverse.difference(b).reverse =23=3D> =5B1,2,3,2=5D=60Array=23= difference=21=60 could be defined in the obvious way.-- https://bugs.ruby= -lang.org/ --56738680_1eba5d23_16c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Joseph Jones liked your message with Boxer.


= On December 14, 2015 at 01:27:10 MST, cary=40swoveland.com wrote:
Issue =2311815 has been repor= ted by Cary Swoveland.

---------------------------------------= -
=46eature =2311815: Proposal for method =60Array=23difference=60https://bugs.ruby-lang.org/issues/11815

* Author: Cary Swo= veland
* Status: Open
* Priority: Normal
* Assignee:
----------------------------------------
I propose that a method =60= Array=23difference=60 be added to the Ruby core. It is similar to =5BArra= y=23-=5D(http://ruby-doc.org/core-2.2.0/Array.html=23method-i-2D) but for= each element of the (array) argument it remove only one matching element= from the receiver. =46or example:

a =3D =5B1,2,3,4,3,2,2,= 4=5D
b =3D =5B2,3,4,4,4=5D

a - b =23= =3D> =5B1=5D
c =3D a.difference b =23=3D> =5B1, 3, 2, 2=5D

As you see, =60a=60 contains three =602=60's and =60b=60 =601=60, = so the first =603-1 =23=3D> 2=60 =602=60's in =60a=60 have been removed f= rom =60a=60 in constructing =60c=60. When =60b=60 contains as least as ma= ny instances of an element as does =60a=60, =60c=60 contains no instances= of that element.

It could be implemented as follows:
class Array
def difference(other)
dup.= tap do =7Ccpy=7C
other.each do =7Ce=7C
= ndx =3D cpy.index(e)
cpy.delete=5Fat(ndx) if ndx
= end
end
end
end
Here are a few examples of its use:

*Identify an array's n= on-unique elements*

a =3D =5B1,3,2,4,3,4=5D
u= =3D a.uniq =23=3D> =5B1, 2, 3, 4=5D
u - a.difference= (u) =23=3D> =5B1, 2=5D

*Determine if two words of the same siz= e are anagrams of each other*

w1, w2 =3D =22stop=22, =22= pots=22
w1.chars.difference(w2.chars).empty=3F
=23= =3D> true

*Identify a maximal number of 1-1 matches between th= e elements of two arrays and return an array of all elements from both ar= rays that were not matched*

a =3D =5B1, 2, 4, 2, 1, 7, 4= , 2, 9=5D
b =3D =5B4, 7, 3, 2, 2, 7=5D
a.differen= ce(b).concat(b.difference(a))
=23 =3D> =5B1, 1, 4, 2, 9, 3, = 7=5D

To remove elements from =60a=60 starting at the end (r= ather the beginning) of =60a=60:

a =3D =5B1,2,3,4,3,2,2,4=5D=
b =3D =5B2,3,4,4,4=5D

a.reverse.difference(b).re= verse =23=3D> =5B1,2,3,2=5D

=60Array=23difference=21=60 could = be defined in the obvious way.



--
https://bu= gs.ruby-lang.org/
--56738680_1eba5d23_16c--