2016-01-11 13 views
10

Fornisci un metodo che somma tutti i numeri in un list. Il metodo dovrebbe essere in grado di saltare elementi che non sono numeri. Quindi, sum([1, 2, 3]) dovrebbe essere 6 ma sum(['A', 1, 'B', 2, 3])dovrebbe anche essere 6. Come posso realizzare questo?sommando solo i numeri contenuti in un elenco

quello che ho già provato finora:

def foo(list): 
    dict = "ABCDEFGHIJKLMN" 
    n = 0 
    for i in range(0, len(list) - 1): 
     if list[i].str in dict: 
      "" 
     else:  
      n= n + list[i] 
    return n 

print foo([1, 2, 3, 4, 5, 6, "A", "B"]) 
+0

Sostituire 'elenco [i] .str' con' str (elenco [i]) '. – Delgan

+1

Mi sembra un compito a casa. –

+0

@ JonasGröger Ha pubblicato il codice che ha scritto credo. – Delgan

risposta

17

Si può fare questo con un semplice rivestimento:

l1 = [1, 2, 3, 'A'] 

sum(filter(lambda i: isinstance(i, int), l1)) 
# prints 6 

Oppure, se ne avete bisogno all'interno di una funzione:

def foo(l1): 
    return sum(filter(lambda i: isinstance(i, int), l1)) 

Inoltre, come indicato nei commenti, non utilizzare nomi come dict e list per le variabili; * ombreggiano i nomi predefiniti per i dizionari (dict) e (list). Dovrai quindi esplicitamente del dict, list per utilizzarli come previsto.


Ma, lasciatemi spiegare. Nei filter fa, qui è:

a) Prende una funzione come primo parametro:

# this function will return True if i is an int 
# and false otherwise 
lambda i: isinstance(i, int) 

e poi prende ogni elemento all'interno della lista l1 (secondo argomento) e valuta se sia è True o False in base alla funzione.

b) Quindi, filter sarà essenzialmente filtrare qualsiasi oggetto lista l1 interne che non sono istanze di int (cioè la funzione restituisce False per loro). Di conseguenza, per un elenco come [1, 2, 3, 'A'] il filtro restituirà [1, 2, 3] che verrà quindi riassunto da sum().

Alcuni esempi:

foo([1, 2, 3, 'A']) 
# 6 

foo([1, 2, 3]) 
# 6 

foo([1, 2, 3, 'HELLO', 'WORLD']) 
# 6 

Leggero avvertimento:

Come è, questo non significa riassumere float valori, li (e altri tipi numerici gocce per quel caso). Se avete bisogno anche questo, è sufficiente aggiungere il tipo di float nella funzione lambda come così:

lambda i: isinstance(i, (int, float)) 

Ora, le vostre somme funzione galleggia troppo:

foo([1, 2, 3, 3.1, 'HELLO', 'WORLD']) 
# 9.1 

aggiungere altri tipi come necessario nella funzione lambda per prendere i casi che ti servono.


Una cattura tutti i casi:

Come notato da @Copperfield è possibile verificare la presenza di oggetti che sono istanze di qualsiasi numero utilizzando la classe di base astratta numbers.Number nel numbers modulo. Questo agisce come catch-all caso per i valori numerici:

import numbers # must import 
sum(filter(lambda i: isinstance(i, numbers.Number), l1)) 

semplice e un po 'più veloce, troppo:

Inoltre, come osservato da @ShadowRanger, e poiché lambda might not be the most comfortable construct for new users, si potrebbe semplicemente utilizzare a generator expression (che è anche più veloce) con sum per ottenere lo stesso risultato esatto:

sum(val for val in l1 if isinstance(val, numbers.Number)) 
+2

per includere tutti i tipi numerici senza menzionarli singolarmente, è possibile utilizzare il corrispondente [ABC] (https://docs.python.org/3/library/numbers.html), ad esempio 'isinstance (item, numbers.Number) ' – Copperfield

+3

Se aveste bisogno di un' lambda' per usare 'map' /' filter', potreste anche usare un'espressione di generatore (o lista comp); non guadagni nulla in termini di brevità o velocità non appena fai ricorso a 'lambda's con' map'/'filter'. – ShadowRanger

+0

La perdita di velocità è trascurabile in questo contesto, ma esiste comunque, modifico il mio asnwer per includere il 'somma' basato sul generatore poiché è anche più esplicito. La più grande perdita qui è probabilmente dovuta al fatto che 'lambda' è un costrutto strano e confonde le persone, specialmente i nuovi arrivati. –

4

filtro uso e isinstance come questo

>>> test = [1,2,3,4,5,6,"A","B"] 
>>> sum(filter(lambda x:isinstance(x,int),test)) 
21 
>>> 
8
sum([x for x in list if isinstance(x, (int, long, float))]) 
+0

La migliore risposta. Forse usare filter() sarebbe più esplicito. – felipsmartins

+2

'filter' è davvero solo" migliore "quando ti guadagna qualcosa in velocità o brevità (e guadagna solo la velocità quando puoi passarlo una funzione built-in implementata in C su CPython).Per qualcosa di simile, un'espressione di generatore è la migliore (come la risposta corrente, ma senza le parentesi che fanno una comprensione 'list', il che significa che nessuna' lista intermedia 'viene creata e gettata via); non è più o meno esplicito e probabilmente è leggermente più veloce. – ShadowRanger

10

Il modo Pythonic è quello di fare un try/except. Mentre potresti farlo in una sola nave, preferisco spezzare un po 'le cose per vedere esattamente cosa sta succedendo.

val=0 
for item in list: 
    try: 
     val+=int(item) 
    except ValueError: 
     pass 

Se si desidera includere punti di galleggiamento, è sufficiente modificare il int ad un float. I punti mobili sono qualsiasi cosa con un decimale, tra gli altri.

+4

Non sei sicuro del motivo per cui sei stato votato. Se questo fosse qualcosa di più complicato di "Aggiungi i numeri", allora questo è esattamente *** come farlo. Lo sfacciato one-liner non è migliore. –

+1

@AdamSmith: Purtroppo è così. Troppi programmatori Python amano provare a stipare il più possibile in un'unica riga di codice ... – PearsonArtPhoto

+2

Mentre io ho fatto +1 e in generale sono d'accordo (come ha detto Adam, in casi più complicati), * in questo caso * un 'try-catch' è eccessivo. Inoltre, si sta eseguendo il wraping di un 'item' in una chiamata' int' quando in realtà non dovrebbe essere necessario e, al fine di generalizzare per comprendere tutti i numeri, probabilmente si eseguirà un 'if isinstance' e si eliminerà' try'. del tutto. 'filter' è una funzione così meravigliosa per esattamente queste cose, non riesco a capire perché ci stai sopra. –

3
def foo(list): 
dict= "ABCDEFGHIJKLMN" 
n=0 
for i in range(0,len(list)-1): 
    if str(list[i]) in dict: 
     "" 
    else:  
     n= n+list[i] 
return n 
print foo([1,2,3,4,5,6,"A","B"]) 
+0

Perché hai aggiunto il codice sbagliato come risposta? Puoi cancellarlo. – Parth

+0

funziona ora da str (list [i]) – user3419487

+0

Ma non funzionerà se si dispone di stringhe oltre a A-N. Per esempio. Prova "Z" – Parth

1
def filtersum(L): 
    if not L: return 0 
    if not isinstance(L[0], int): return filtersum(L[1:]) 
    return L[0] + filtersum(L[1:]) 

uscita:

In [28]: filtersum([1,2,3]) 
Out[28]: 6 

In [29]: filtersum([1,'A', 2,3]) 
Out[29]: 6 
+2

perché la ricorsione? non è necessario overhead – Copperfield

+0

OP vuole le risposte per un esame - Immagino che un professore sarebbe molto impressionato da questa risposta dello studente in una introduzione alla classe di programmazione – inspectorG4dget

+1

Un blocco di codice da solo non fornisce una buona risposta. Per favore aggiungi spiegazioni (perché risolve il problema, dov'era l'errore, ecc ...) –

Problemi correlati