[Python] Il dilemma degli array mutabili

Riccardo Lemmi riccardo a reflab.com
Gio 19 Set 2013 17:58:05 CEST


Piergiuliano Bossi wrote:

> 2013/9/18 Riccardo Lemmi <riccardo a reflab.com>
> 
>>
>>
>> Mi sfugge il caso, forse un esempio chiarirebbe... L'unico posto in
>> cui vedo male il codice messo sopra è quello in cui si usano gli
>> elementi dell'array non in sequenza ma pescando in "qua e la'"
>>
>>
> Ho visto la luce.
> 
> Questo e' il codice che ha causato il thread (semplificato,
> ovviamente);
> 
> def evaluate(list):
>     return sum(v for v in list if v % 2 == 0)
> 
> def _subtract(list1, list2):
>     result = list1[:]
>     for val in list2:
>         result.remove(val)
>     return result

Manca un check prima di fare il remove. Alternativamente la scriverei 
così:

def _subtract(list1, list2):
    result = []
    for val in list2:
        if val not in list2:
             result.append(val)
    return result

ma se non ci sono ridondanze nelle due liste cioè stai effettivamento 
implementando la differenza fra insiemi:

result = set(list1) - set(list2)

o

result = set(list1).difference(list2) 

> def useless(list):
>     useful = list[:]
>     for val in list:
>         useful.remove(val)
>         if evaluate(useful) != evaluate(list):
>             useful.append(val)
>     return _subtract(list, useful)
> 
> if __name__ == "__main__":
>     print(useless([]))    # => []
>     print(useless([1, 2, 3, 5, 8]))    # => [1, 3, 5]
> 
> Codice abbastanza orrido, no?
> 
> L'idea e' calcolare gli elementi di una lista che non contribuiscono
> al valore determinato da una certa funzione. Diciamo che evaluate in
> realta' e' molto piu' complessa (non computazionalmente, ma
> matematicamente non e' semplice), che e' insensibile all'ordine degli
> elementi nella lista (da cui l'uso di remove non posizionale) e che
> ovviamente questo codice non e' ottimizzato (eg: e' inutile chiamare
> evaluate(list) ogni volta nel ciclo).
> 

detto così sembra proprio che tu stia lavorando con i set...

> L'ho riscritto senza copy.copy ma con [:] e ovviamente tutto bene, ma
> non e' un gran guadagno. Poi ho provato a fare una comprehension che
> fa tutto al volo e mi e' venuta al primo colpo:
> 
> def useless(list):
>     return [list[i] for i in range(len(list)) if evaluate(list[:i] +
> list[i+1:]) == evaluate(list)]
> 
> Oserei dire che e' persino un pelo piu' comunicativa cosi', visto che
> non devo calcolare una lista e poi sottrarla all'altra.
> Mi sento come se avessi trovato il barattolo di nutella di Moretti, un
> cucchiaione e nessuno attorno...  :)
> 
> Ciao
> Giuliano
> 
> PS: queste sono le cose che fanno scattare l'ammmmore...
> 
> 

-- 
                                       Riccardo Lemmi



Maggiori informazioni sulla lista Python