This project is archived and is in readonly mode.
Adding Array.uniq_by(proc) to core_ext, allowing selection of unique elements based on their response to a proc
Reported by Joey Schoblaska | July 25th, 2009 @ 11:46 PM | in 3.0.2
Oftentimes it's necessary to select some unique elements from an array based on various attributes. For instance, if you have an array of posts and you want to select only posts that have a unique author_id; or posts with a unique combination of author_id and created_at date to get an array with one post per user per day. It's usually possible to do this with SQL when you're dealing with AR objects, but that's not always an option, so I wrote this patch to address those cases.
array = [{:id => 1, :val => 1},
{:id => 2, :val => 1},
{:id => 3, :val => 2},
{:id => 4, :val => 3}]
array.uniq_by(Proc.new {|a| a[:val]}).map{|a| a[:id]} == [1,3,4]
Comments and changes to this ticket
-
Joey Schoblaska July 27th, 2009 @ 04:17 PM
I can't download the original attachment, so trying another upload to see if that fixes it.
-
Joey Schoblaska July 27th, 2009 @ 04:18 PM
- no changes were found...
-
Yehuda Katz (wycats) July 28th, 2009 @ 03:13 AM
- State changed from new to open
- Assigned user set to Yehuda Katz (wycats)
- Milestone cleared.
Looks good to me. Are there any parts of the Rails internals that you could see benefiting from this patch?
-
Joey Schoblaska July 28th, 2009 @ 04:41 AM
Thanks! I can't think of any off the top of my head, but I'll definitely take a look.
-
Elliot Winkler July 28th, 2009 @ 07:29 PM
+1 for the idea. I wrote a version of the method a while back (except using inject + a hash instead of a select within a select as you've got). It does come in handy.
Question: Why does your uniq_by accept a Proc object? Shouldn't it just accept a block? I.e.:
arr.uniq_by {|x| ... }
as opposed to
arr.uniq_by(Proc.new {|x| ... })
-
Joey Schoblaska July 29th, 2009 @ 01:33 AM
Thanks for the suggestion. You're right - blocks result in much nicer-looking method calls than procs. I updated the patch to use blocks instead.
-
Pratik July 31st, 2009 @ 10:45 PM
Why not just override Array#uniq and uniq! instead of adding a new method ?
-
Joey Schoblaska August 1st, 2009 @ 12:27 AM
It seemed like overriding a Ruby method as common as [].uniq might cause confusion so I opted to create a new, explicitly-named method instead.
-
Pratik August 1st, 2009 @ 12:47 AM
I think doing something like this might be ok :
def uniq if block_give? select {|item| select {|i| yield(i) == yield(item)}.index(item) == 0 } else super end end
Just a thought. I'm fine with a new method too. I just think it's more intuitive to make uniq accept a block.
-
Dan Barry August 1st, 2009 @ 09:53 PM
Joey's implementation O(n^3 / m) where n is the number of elements in the array and m is the number of unique values. I came up with a different implementation that is more performant: http://gist.github.com/159799
-
Cheah Chu Yeow August 3rd, 2009 @ 02:21 AM
I like Pratik's idea of overriding uniq. There've been more than a few times that I've used uniq expecting that it takes a block.
Otherwise I like the general idea of this patch :)
-
Evgeniy Dolzhenko August 10th, 2009 @ 10:24 AM
+1 since was always using the same method for a long time available in Facets http://facets.rubyforge.org/git?p=facets.git;a=blob_plain;f=lib/cor...
Also if you guys came with more efficient implementation I think it's worth sending it to Facets as well.
-
Evgeniy Dolzhenko August 10th, 2009 @ 10:28 AM
Ok, the Facets link got crippled, here is the shortened one http://bit.ly/QMjcp
-
jack dempsey (jackdempsey) October 28th, 2009 @ 03:28 PM
+1 I could use something like this right now. Dan's patch is nice as well--those speed improvements are excellent.
-
Dan Peterson December 10th, 2009 @ 09:46 PM
Just discovered this ticket while Googling for my version of Enumerable#uniq_by. ;)
Here's the version I came up with if it helps: http://gist.github.com/168544
-
José Valim February 3rd, 2010 @ 09:56 AM
- State changed from open to resolved
- Assigned user changed from Yehuda Katz (wycats) to José Valim
That was already added on master.
-
Jeremy Kemper October 15th, 2010 @ 11:01 PM
- Milestone set to 3.0.2
- Importance changed from to
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>