From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: poffice@blade.nagaokaut.ac.jp Delivered-To: poffice@blade.nagaokaut.ac.jp Received: from kankan.nagaokaut.ac.jp (kankan.nagaokaut.ac.jp [133.44.2.24]) by blade.nagaokaut.ac.jp (Postfix) with ESMTP id 8BBAA19E0025 for ; Tue, 15 Dec 2015 20:55:15 +0900 (JST) Received: from voscc.nagaokaut.ac.jp (voscc.nagaokaut.ac.jp [133.44.1.100]) by kankan.nagaokaut.ac.jp (Postfix) with ESMTP id 92508B5D8D4 for ; Tue, 15 Dec 2015 21:27:14 +0900 (JST) Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by voscc.nagaokaut.ac.jp (Postfix) with ESMTP id 5470718CC7EA for ; Tue, 15 Dec 2015 21:27:15 +0900 (JST) Received: from [221.186.184.76] (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 77F861204B1; Tue, 15 Dec 2015 21:27:12 +0900 (JST) X-Original-To: ruby-core@ruby-lang.org Delivered-To: ruby-core@ruby-lang.org Received: from o10.shared.sendgrid.net (o10.shared.sendgrid.net [173.193.132.135]) by neon.ruby-lang.org (Postfix) with ESMTPS id 956F4120492 for ; Tue, 15 Dec 2015 21:27:08 +0900 (JST) DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sendgrid.me; h=from:to:references:subject:mime-version:content-type:content-transfer-encoding:list-id; s=smtpapi; bh=u4vvKPLHjSG3M+9gu94V57nDQCQ=; b=VbIP24nmFBb/xCIblH vyGTeMAC4KKkMbiUM1TjOnjuZdnoaI8PupIi4aXa/gT3nc2DFh0QC0UWG0lV0fez J7UbRE3SYYqrJNDt0/s5c1NyNGwCLKoPuykRwhdOjtvXFx9mL2ies6KTC023XNUc /tQrtBs5HFgcZkCq6w+vpi720= Received: by filter0918p1mdw1.sendgrid.net with SMTP id filter0918p1mdw1.8275.567007174D 2015-12-15 12:27:03.603208204 +0000 UTC Received: from herokuapp.com (ec2-54-163-84-228.compute-1.amazonaws.com [54.163.84.228]) by ismtpd0004p1iad1.sendgrid.net (SG) with ESMTP id qXOc527gTZOCoxaNPo_ikA for ; Tue, 15 Dec 2015 12:27:03.976 +0000 (UTC) Date: Tue, 15 Dec 2015 12:27:03 +0000 From: 6ftdan@gmail.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Redmine-MailingListIntegration-Message-Ids: 46849 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 11815 X-Redmine-Issue-Author: CaryInVictoria X-Redmine-Sender: danielpclark X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS7a1HFn9DETO8T8qFBZB4g9EvrMt0Doo83DAP NAARQn9vcaTSbu7QlKFFMr5h+p/3NU+Mv+7pXm0q/8Ww+ZYzTuTch0HS8W1mEYMmQ0rl1yL2dzFuS6 ywqJEi32ZJAVaAz5ICgB2KAsTe7IBnzNoP93 X-SendGrid-Contentd-ID: {"test_id":"1450182425"} X-ML-Name: ruby-core X-Mail-Count: 72143 Subject: [ruby-core:72143] [Ruby trunk - Feature #11815] Proposal for method `Array#difference` X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: ruby-core-bounces@ruby-lang.org Sender: "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/