Clarify Array#- and Array#difference documentation

Currently we are not explicit enough regarding the potentially confusing
behavior of `Array#-` and `Array#difference` when it comes to duplicate items
within receiver arrays.

Although the original documentation for these methods does use an array with
multiple instance of the same integers, the explanation for the behavior is
actually imprecise.

> removing any items that also appear in +other_ary+

Not only does `Array#-` remove any items that also appear in `other_ary` but
it also remove any instance of any item in `other_ary`.

One may expect `Array#-` to behave like mathematical subtraction or difference
when it doesn't. One could be forgiven to expect the following behavior:

```ruby
[1,1,2,2,3,3,4,4] - [1,2,3,4]
=> [1,2,3,4]
```

In reality this is the result:

```ruby
[1,1,2,2,3,3,4,4] - [1,2,3,4]
=> []
```

I hope that I've prevented this potential confusion with the clarifications
in this change. I can offer this as evidence of likeliness for confusion:
https://twitter.com/olivierlacan/status/1084930269533085696

I'll freely admit I was surprised by this behavior myself since I needed to
obtain an Array with only one instance of each item in the argument array
removed.

[Fix GH-2068] [ci skip]

From: Olivier Lacan <hi@olivierlacan.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66831 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2019-01-15 13:52:38 +00:00
Родитель d7976d1451
Коммит 10d85b19da
1 изменённых файлов: 19 добавлений и 6 удалений

25
array.c
Просмотреть файл

@ -4452,14 +4452,18 @@ ary_recycle_hash(VALUE hash)
*
* Array Difference
*
* Returns a new array that is a copy of the original array, removing any
* items that also appear in +other_ary+. The order is preserved from the
* original array.
* Returns a new array that is a copy of the original array, removing all
* instances of any item that also appear in +other_ary+. The order is preserved
* from the original array.
*
* It compares elements using their #hash and #eql? methods for efficiency.
*
* [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
*
* Note that while 1 and 2 were only present once in the array argument, and
* were present twice in the receiver array, all instances of each Integer are
* removed in the returned array.
*
* If you need set-like behavior, see the library class Set.
*
* See also Array#difference.
@ -4499,13 +4503,22 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
*
* Array Difference
*
* Returns a new array that is a copy of the receiver, removing any items
* that also appear in any of the arrays given as arguments.
* The order is preserved from the original array.
* Returns a new array that is a copy of the original array, removing all
* instances of any item that also appear in +other_ary+. The order is
* preserved from the original array.
*
* It compares elements using their #hash and #eql? methods for efficiency.
*
* [ 1, 1, 2, 2, 3, 3, 4, 5 ].difference([ 1, 2, 4 ]) #=> [ 3, 3, 5 ]
*
* Note that while 1 and 2 were only present once in the array argument, and
* were present twice in the receiver array, all instances of each Integer are
* removed in the returned array.
*
* Multiple array arguments can be supplied and all instances of any element
* in those supplied arrays that match the receiver will be removed from the
* returned array.
*
* [ 1, 'c', :s, 'yep' ].difference([ 1 ], [ 'a', 'c' ]) #=> [ :s, "yep" ]
*
* If you need set-like behavior, see the library class Set.