2012-07-31 9 views
7

Sto provando a raggruppare un array di numeri interi in un hash in base a dove i singoli valori rientrano in un intervallo. Fondamentalmente voglio convertire una matrice in un istogramma a larghezza fissa.Ruby Array to Histogram: come raggruppare i numeri per intervallo?

Esempio:

values = [1,3,4,4,4,4,4,10,12,15,18] 
bin_width = 3 

devo raggruppare i valori di matrice in un historgram gamma-based dove cadono in un ampio secchio 3 elementi in questo modo:

{'0..2'=>[1,3],'3..5'=>[4,4,4,4,4],'6..8'=>[],'9..11'=>[10].... 

Is c'è una soluzione a linea semplice (forse qualcosa come values.group_by{|x| #range calc}) che funzionerebbe qui?

+1

domande: 1) Credo che 3 dovrebbe essere in 3..5. 2) perché usare le stringhe come chiavi al posto delle gamme reali? 3) hai bisogno anche degli intervalli vuoti? – tokland

+3

non ci dovrebbe essere ossessione per scrivere one-liner. Sforzarsi per soluzioni che riguardano solo espressioni (che è, usando un approccio funzionale) sì, temendo incarichi per salvare un paio di linee, no. – tokland

risposta

10
values = [1, 7, 2, 8, 2] 
values.group_by { |x| x/3 }.map { |k, vs| [(3*k..3*k+2), vs] }.to_h 
#=> {0..2=>[1, 2, 2], 6..8=>[7, 8]} 

Se avete davvero bisogno delle gamme vuote, non penso che sia possibile una linea singola pulita. Ma questo dovrebbe fare:

grouped = values.group_by { |x| x/3 } 
min, max = grouped.keys.minmax 
(min..max).map { |n| [(3*n..3*n+2), grouped.fetch(n, [])] }.to_h 
#=> {0..2=>[1, 2, 2], 3..5=>[], 6..8=>[7, 8]} 
+0

Hah, volevo solo suggerire qualcosa che non richieda faccette e poi hai aggiornato il tuo post. –

+1

@ Michael, si scusa, in effetti il ​​mio frammento di faccette era completamente sbagliato, map_by non è utile qui, dobbiamo elaborare le chiavi, non i valori. È così che lo scriverebbe? – tokland

4

mi si avvicinò con una soluzione piuttosto inefficiente ma abbastanza chiaro:

ranges = 0.step(values.max, bin_width).each_cons(2).map { |s, e| Range.new(s, e, true) } 
values.group_by { |v| ranges.find { |r| r.cover? v } } 
+0

Grazie per la versione più generale che funziona con bidoni a 3 unità e può adattarsi a casi più arbitrari. Proprio quello di cui avevo bisogno. – slothbear