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) endAlternativamente, 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 complessodef 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 diselect() 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