Contare frequenza su array

ciao a tutti
sto imparando Ruby; per me uno degli aspetti più ostici è capire come
produrre codice ben scritto; Ruby dà la libertà di scegliere fra tanti
modi diversi per ottenere un certo risultato; rimane sempre il dubbio
che esista una strada migliore di quella intrapresa; ad esempio, come si
fa a ottenere la frequenza degli elementi di un array? personalmente ho
prodotto il seguente codice:
a = [1,2,3,4,1,2,3,1,2,1,5,5]
b = {}
a.uniq.each {|x| b[x] = a.find_all {|y| y == x}.size}
p b
che produce
{5=>2, 1=>4, 2=>3, 3=>2, 4=>1}
esistono modi più puliti o efficienti di ottenere lo stesso risultato?
c’è modo di scrivere su un’unica riga la parte
b = {}
a.uniq.each {|x| b[x] = a.find_all {|y| y == x}.size}
p b
?
grazie

On Wed, Feb 4, 2009 at 8:19 AM, Giampiero Z. [email protected] wrote:

che esista una strada migliore di quella intrapresa; ad esempio, come si
fa a ottenere la frequenza degli elementi di un array? personalmente ho
prodotto il seguente codice:
a = [1,2,3,4,1,2,3,1,2,1,5,5]

Io farei
così:
a.inject(Hash.new(0)) { |hash, item| hash[item] += 1; hash }

Ciao,
Antonio

http://antoniocangiano.com - Zen and the Art of Programming
http://math-blog.com - Mathematics is wonderful!
http://stacktrace.it - Aperiodico di resistenza informatica
Currently writing “Ruby on Rails for Microsoft Developers” for Wrox.

Antonio C. wrote:

Io farei
cos�:
a.inject(Hash.new(0)) { |hash, item| hash[item] += 1; hash }

Ciao,
Antonio

intanto grazie mille per la pronta risposta
ecco, avevo visto giusto che c’era una via più breve e pulita; anch’io
avevo tentato la strada con inject, ma non avevo trovato il modo di
indicare che volevo ‘totalizzare’ su un hash inizialmente vuoto; fra
l’altro ho notato che se faccio precedere il tutto da p
p a.inject(Hash.new(0)) { |hash, item| hash[item] += 1; hash }
ottengo in output proprio l’hash; quindi la inject ritorna proprio
l’oggetto su cui ho ‘totalizzato’;
Ruby è troppo perfetto! fa sempre quello che ti aspetti

On Wed, Feb 4, 2009 at 8:37 AM, Giampiero Z. [email protected] wrote:

Giampiero Z. wrote:
ah, no, l’ho capito solo ora; è grazie a ; hash alla fine del blocco che
ho l’hash come oggetto ritornato; dico bene? ho imparato un’altra cosa,

Esattamente. L’ultima espressione valutata nel blocco sarà il valore
di ritorno per la prossima iterazione, per cui ci serve hash che
agisce come accumulatore.

Ciao,
Antonio

http://antoniocangiano.com - Zen and the Art of Programming
http://math-blog.com - Mathematics is wonderful!
http://stacktrace.it - Aperiodico di resistenza informatica
Currently writing “Ruby on Rails for Microsoft Developers” for Wrox.

Giampiero Z. wrote:
ah, no, l’ho capito solo ora; è grazie a ; hash alla fine del blocco che
ho l’hash come oggetto ritornato; dico bene? ho imparato un’altra cosa,
grazie di nuovo

On 2/4/09 2:19 PM, Giampiero Z. wrote:

p b
che produce
{5=>2, 1=>4, 2=>3, 3=>2, 4=>1}
esistono modi più puliti o efficienti di ottenere lo stesso risultato?
c’è modo di scrivere su un’unica riga la parte
b = {}
a.uniq.each {|x| b[x] = a.find_all {|y| y == x}.size}
p b

La soluzione più elegante che mi venga in mente su 2 piedi:

a.inject(Hash.new(0)) { |h, v| h[v] += 1; h }

Una soluzione “offuscante” può essere:

b = Hash.new(0)
a.each { |x| b.merge!({x => 1}) { |k, o, n| o+n } }

Andrea

Giampiero Z. wrote:

b = Hash.new(0)
a.each { |x| b.merge!({x => 1}) { |k, o, n| o+n } }

Andrea
grazie Andrea
la tua prima soluzione è praticamente identica a quella di Antonio; se
si ripete mi sa che è “la più giusta assai” :slight_smile:
per la seconda sono sempre qui che mi scervello, eppure funziona!!! più
che altro non capisco chi “chiama” il secondo blocco (?!?)

ah, ho capito; non conoscevo questa variante della merge; imparata una
nuova cosa;
grazie mille e a buon rendere (chissà ?!)
Giampiero

La soluzione pi� elegante che mi venga in mente su 2 piedi:

a.inject(Hash.new(0)) { |h, v| h[v] += 1; h }

Una soluzione “offuscante” pu� essere:

b = Hash.new(0)
a.each { |x| b.merge!({x => 1}) { |k, o, n| o+n } }

Andrea
grazie Andrea
la tua prima soluzione è praticamente identica a quella di Antonio; se
si ripete mi sa che è “la più giusta assai” :slight_smile:
per la seconda sono sempre qui che mi scervello, eppure funziona!!! più
che altro non capisco chi “chiama” il secondo blocco (?!?)