Forum: Italian Ruby user group contare frequenza su array

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Giampiero Z. (Guest)
on 2009-02-04 15:19
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
Antonio C. (Guest)
on 2009-02-04 15:29
(Received via mailing list)
On Wed, Feb 4, 2009 at 8:19 AM, Giampiero Z. 
<removed_email_address@domain.invalid> 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.
Giampiero Z. (Guest)
on 2009-02-04 15:35
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
Giampiero Z. (Guest)
on 2009-02-04 15:37
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
Antonio C. (Guest)
on 2009-02-04 15:41
(Received via mailing list)
On Wed, Feb 4, 2009 at 8:37 AM, Giampiero Z. 
<removed_email_address@domain.invalid> 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.
Andrea C. (Guest)
on 2009-02-04 16:09
(Received via mailing list)
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. (Guest)
on 2009-02-04 16:34
>
> 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" :-)
per la seconda sono sempre qui che mi scervello, eppure funziona!!! più
che altro non capisco chi "chiama" il secondo blocco (?!?)
Giampiero Z. (Guest)
on 2009-02-04 16:38
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" :-)
> 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
This topic is locked and can not be replied to.