; docformat = 'rst' ;+ ; Finds the `n` smallest elements of a data array. This algorithm works ; fastest on uniformly distributed data. The worst case for it is a single ; smallest data element and all other elements with another value. This will ; be nearly equivalent to just sorting all the elements and choosing the first ; `n` elements. ; ; :Examples: ; For example, to find the 3 smallest values of 10 random values, try:: ; ; IDL> r = randomu(seed, 10) ; IDL> print, r, format='(4F)' ; 0.6297589 0.7815896 0.2508559 0.7546844 ; 0.1353382 0.1245834 0.8733745 0.0753110 ; 0.8054136 0.9513228 ; IDL> ind = mg_n_smallest(r, 3) ; IDL> print, r[ind] ; 0.0753110 0.124583 0.135338 ; ; :Returns: ; index array ; ; :Params: ; data : in, required, type=numeric array ; data array of any numeric type (except complex/dcomplex) ; n : in, required, type=integer ; number of smallest elements to find ; ; :Keywords: ; largest : in, optional, type=boolean ; set to find `n` largest elements ;- function mg_n_smallest, data, n, largest=largest compile_opt strictarr on_error, 2 ; both parameters are required if (n_params() ne 2) then message, 'required parameters are missing' ; use histogram to find a set with more elements than n of smallest elements nData = n_elements(data) nBins = nData / n h = histogram(data, nbins=nBins, reverse_indices=ri) ; set parameters based on whether finding smallest or largest elements if (keyword_set(largest)) then begin startBin = nBins - 1L endBin = 0L inc = -1L endif else begin startBin = 0L endBin = nBins - 1L inc = 1L endelse ; loop through the bins until we have n or more elements nCandidates = 0L for bin = startBin, endBin, inc do begin nCandidates += h[bin] if (nCandidates ge n) then break endfor ; get the candidates and sort them candidates = keyword_set(largest) ? $ ri[ri[bin] : ri[nBins] - 1L] : $ ri[ri[0] : ri[bin + 1L] - 1L] sortedCandidates = sort(data[candidates]) if (keyword_set(largest)) then sortedCandidates = reverse(sortedCandidates) ; return the proper n of them return, (candidates[sortedCandidates])[0:n-1L] end