From: "Hanmac (Hans Mackowiak)" Date: 2013-09-10T23:03:26+09:00 Subject: [ruby-core:57112] [ruby-trunk - Feature #8887] min(n), max(n), min_by(n), max_by(n) Issue #8887 has been updated by Hanmac (Hans Mackowiak). hm i am curios in what order max(n) and max_by(n) should return the elements? like [6, 0, 3, 3, 8, 3, 5, 0, 6].max(4): should it return sort.last(n) #> [5, 6, 6, 8] or is that better? [8, 6, 6, 5] because 8 is bigger than 6 ? PS: min_by(n) and max_by(n) (and maybe sort_by(n)) should maybe implemented different without take, so that it max_by(n) picks only the first n biggest objects without sorting the entire test of the Enumerator? also about your patch, e.min_by(n).size should respect also n and also enum_size, so it needs to return n when n < as size, and size when n > size (for size != nil) ---------------------------------------- Feature #8887: min(n), max(n), min_by(n), max_by(n) https://bugs.ruby-lang.org/issues/8887#change-41723 Author: akr (Akira Tanaka) Status: Open Priority: Normal Assignee: Category: Target version: How about adding an optional argument, n, for Enumerable#{min,max,min_by,max_by} to return minimum/maximum n elements as an array. Example: * [6, 0, 3, 3, 8, 3, 5, 0, 6].min(4) #=> [0, 0, 3, 3] * [6, 0, 3, 3, 8, 3, 5, 0, 6].max(4) #=> [5, 6, 6, 8] * [6, 0, 3, 3, 8, 3, 5, 0, 6].min_by(4) {|v| (v-5)**2 } #=> [5, 6, 6, 3] * [6, 0, 3, 3, 8, 3, 5, 0, 6].max_by(4) {|v| (v-5)**2 } #=> [3, 8, 0, 0] These methods are similar to sort follows first or last. * e.min(n) is similar to e.sort.first(n) * e.max(n) is similar to e.sort.last(n) * e.min_by(n) {...} is similar to e.sort_by {...}.first(n) * e.max_by(n) {...} is similar to e.sort_by {...}.last(n) However e.min(n), e.max(n), e.min_by(n), e.max_by(n) are less memory consuming and can be faster. They use memory proportional to n, not e. They doesn't sort whole e. I feel their use is not rare. I found several use after searching. [ruby-talk:123508], [ruby-list:40939], [ruby-talk:273980] http://d.hatena.ne.jp/mjh/20101024/1287901875 http://stackoverflow.com/questions/11094874/get-top-n-elements-from-ruby-array-of-hash-values http://www.math.kobe-u.ac.jp/~kodama/tips-ruby-sized_pqueue.html https://bitbucket.org/sterlingcamden/topn Also, e.max(n) can be used to implement weighted random sampling. Pavlos S. Efraimidis, Paul G. Spirakis Weighted random sampling with a reservoir Information Processing Letters Volume 97, Issue 5 (16 March 2006) % ./ruby -e ' module Enumerable def wsample(n) self.max_by(n) {|v| rand ** (1.0/yield(v)) } end end e = (-20..20).to_a*10000 a = e.wsample(20000) {|x| Math.exp(-(x/5.0)**2) # normal distribution } # a is 20000 samples from e. p a.length h = a.group_by {|x| x } -10.upto(10) {|x| puts "*" * (h[x].length/30.0).to_i if h[x] } ' 20000 * *** ****** *********** ****************** ***************************** ***************************************** **************************************************** *************************************************************** ******************************************************************** *********************************************************************** *********************************************************************** ************************************************************** **************************************************** *************************************** *************************** ****************** *********** ******* *** * Any comments? -- http://bugs.ruby-lang.org/