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.
64aa4b69fdd7127e6f3ee16ae065a620?d=identicon&s=25 Giampiero Zanchi (giampiz)
on 2009-02-04 14: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
6111b4012d1401ca83fdcea6b1d71237?d=identicon&s=25 Antonio Cangiano (Guest)
on 2009-02-04 14:29
(Received via mailing list)
On Wed, Feb 4, 2009 at 8:19 AM, Giampiero Zanchi <cidza@tin.it> 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.
64aa4b69fdd7127e6f3ee16ae065a620?d=identicon&s=25 Giampiero Zanchi (giampiz)
on 2009-02-04 14:35
Antonio Cangiano 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
64aa4b69fdd7127e6f3ee16ae065a620?d=identicon&s=25 Giampiero Zanchi (giampiz)
on 2009-02-04 14:37
Giampiero Zanchi 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
6111b4012d1401ca83fdcea6b1d71237?d=identicon&s=25 Antonio Cangiano (Guest)
on 2009-02-04 14:41
(Received via mailing list)
On Wed, Feb 4, 2009 at 8:37 AM, Giampiero Zanchi <cidza@tin.it> wrote:
> Giampiero Zanchi 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.
24035e6fafa4c747fa9c8f2e9b39c6fd?d=identicon&s=25 Andrea Campi (Guest)
on 2009-02-04 15:09
(Received via mailing list)
On 2/4/09 2:19 PM, Giampiero Zanchi 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
64aa4b69fdd7127e6f3ee16ae065a620?d=identicon&s=25 Giampiero Zanchi (giampiz)
on 2009-02-04 15: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 (?!?)
64aa4b69fdd7127e6f3ee16ae065a620?d=identicon&s=25 Giampiero Zanchi (giampiz)
on 2009-02-04 15:38
Giampiero Zanchi 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.