Filtrare con select e reject

Vedi tutte le pagine e le modifiche recenti o scarica i sorgenti nella pagina


Supponiamo di voler raccogliere in un Array tutte le linee del nostro file d’esempio che riteniamo lunghe, ciow’ quelle con piu’ di 7 caratteri (si, ok, non sono proprio molto lunghe, ma usate la fantasia :-). Un approccio comune sarebbe:
 def linea_lunga?(linea)
   linea.length > 7
 end
 risultato=[]
 File.new('esempio.txt').each do |l|
   risultato.push(l) if linea_lunga?(l)
 end
Alternativamente, possiamo usare il metodo select(), in questo modo:
 puts File.new('esempio.txt').select { |x| linea_lunga?(x) }

la funzione si preoccupa di costruire al posto nostro un array con i valori che risultano validi per la condizione nel blocco.

E se avessimo avuto bisogno di un ulteriore condizione? Niente di complesso
 def con_numeri(linea)
  /[0-9]/.match(linea)
 end

 puts File.new('esempio.txt').select { |x| linea_lunga?(x) and con_numeri(x) }

Ancora, sapendo che possiamo usare degli oggetti Proc
 lunga=proc do |lin|
  lin.length > 7
 end

 num=proc do |lin|
  /[0-9]/.match(lin)
 end

 puts File.new('esempio.txt').select(&lunga).select(&num)

Facile no?.

Il compagno ideale di select() e’ reject(). Questa funzione restituisce un Array contenente gli elementi per i quali il blocco e’ falso. Cioe’, rigetta tutti quelli che rendono vera la condizione:
 >> [1,2,3,4,5,6,7,8,9,1000].reject {|i| i%2==1 } # i dispari
 => [2, 4, 6, 8, 1000]
Nel piu’ classico stile funzionale, queste funzioni non hanno side effect cioe’ non modificano nulla nella struttura originale. Notate poi, che si tratta di metodi contenuti nel modulo Enumerable e che quindi sono disponibili in qualsiasi struttura definisca each(), sia esso un Array, un Hash, un File o un Socket
Updated on November 26, 2005 13:08 by Ruby Fan (151.37.150.7)