2016-01-11 23 views
10

Geben Sie eine Methode, die alle Zahlen in einem list summiert. Die Methode sollte Elemente überspringen können, die keine Zahlen sind. So sollte sum([1, 2, 3])6 sein, aber sum(['A', 1, 'B', 2, 3])sollte auch6 sein. Wie kann ich das erreichen?summieren nur die Zahlen in einer Liste

Was habe ich schon versucht, so weit:

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

ersetzen 'Liste [i] .str' mit' str (list [i]) '. – Delgan

+1

Klingt nach Hausaufgaben für mich. –

+0

@ JonasGröger Er hat den Code geschrieben, den er geschrieben hat, denke ich. – Delgan

Antwort

17

Sie können dies mit einem einfachen Motto:

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

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

Oder, wenn Sie es brauchen in einer Funktion:

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

Zusätzlich, wie in den Kommentaren erwähnt, nicht Namen wie verwenden dict und list für Ihre Variablen; * Sie überschreiben die eingebauten Namen für die Wörterbücher (dict) und (list). Sie müssen dann explizit del dict, list, um sie wie vorgesehen zu verwenden.


Aber lassen Sie mich erklären. Welche filter tut, ist hier:

a) es eine Funktion als erstes Argument:

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

und dann in der Liste jedes Element nimmt l1 (zweites Argument) und wertet aus, ob es ist True oder False basierend auf der Funktion.

b) Dann wird filter auszufiltern wesentlichen alle Objekte innerhalb l1 Liste, die keine Instanzen von int sind (das heißt die Funktion gibt False für sie). Als Ergebnis wird für eine Liste wie [1, 2, 3, 'A'] Filter [1, 2, 3] zurückgegeben, die dann von sum() zusammengefasst werden.

Einige Beispiele:

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

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

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

Leichte Einschränkung:

Wie ist, diese float Werte nicht zusammenzufassen, es fällt ihnen (und alle anderen numerischen Typen für diesen Fall). Wenn Sie das auch brauchen, fügen Sie einfach den float Typ in der lambda Funktion als so:

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

nun Ihre Funktion Summen schwimmt auch:

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

Fügen Sie alle anderen Arten als notwendig in der lambda Funktion um die Fälle zu erfassen, die Sie brauchen.


Ein Fang alle Fall:

Als @Copperfield von bemerkt können Sie für Objekte überprüfen, die in der numbers unter Ausnutzung der numbers.Number abstrakte Basisklasse Instanzen einer beliebigen Anzahl sind Modul. Dies dient als Catch-All-Fall für numerische Werte:

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

Einfachere und ein bisschen schneller, auch:

Zusätzlich wird, wie von @ShadowRanger erwähnt, und da lambda might not be the most comfortable construct for new users, man konnte einfach verwenden a generator expression (das ist auch schneller) mit sum exakt das gleiche Ergebnis zu erhalten:

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

um jeden numerischen Typ aufzunehmen ohne ihn zu erwähnen, können Sie das entsprechende [ABC] (https://docs.python.org/3/library/numbers.html) verwenden, zum Beispiel 'isinstance (item, numbers.Number) ' – Copperfield

+3

Wenn Sie ein' Lambda' benötigen, um 'map' /' filter' zu verwenden, können Sie auch einfach einen Generator-Ausdruck (oder Listen-Comp) verwenden; Sie erhalten nichts in Bezug auf die Kürze oder Geschwindigkeit, sobald Sie zu 'Lambda' mit 'map' /' filter' greifen. – ShadowRanger

+0

Der Geschwindigkeitsverlust ist in diesem Zusammenhang vernachlässigbar, existiert aber nichtsdestotrotz bearbeite ich meinen asnwer, um die Generator-basierte 'Summe' einzuschließen, da sie auch am deutlichsten ist. Der größte Verlust hier ist wahrscheinlich darauf zurückzuführen, dass "Lambda" ein merkwürdiges Konstrukt ist und verwirrende Menschen, insbesondere Neuankömmlinge, verwirrt. –

4

Verwendung Filter und isinstance wie diese

>>> 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

Beste Antwort. Vielleicht wäre die Verwendung von filter() expliziter. – felipsmartins

+2

'filter' ist wirklich nur" besser ", wenn es dir etwas an Geschwindigkeit oder Kürze bringt (und es bringt dir nur Geschwindigkeit, wenn du es einer eingebauten Funktion übergeben kannst, die in C auf CPython implementiert ist).Für so etwas ist ein Generatorausdruck am besten (genauso wie die aktuelle Antwort, aber ohne die Klammern, die ein "Listen" -Verstehen machen, was bedeutet, dass keine Zwischenliste erstellt und weggeworfen wird); es ist nicht mehr oder weniger explizit und wahrscheinlich etwas schneller. – ShadowRanger

10

Der Pythonic Weg ist einen Versuch zu tun/ausgenommen. Während du das in einem einzigen Liner machen könntest, ziehe ich es vor, die Dinge ein wenig zu durchbrechen, um genau zu sehen, was passiert.

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

Wenn Sie Punkte floating aufnehmen möchten, einfach die int zu einem float ändern. Gleitende Punkte sind unter anderem alles mit einer Dezimalzahl.

+4

Nicht sicher, warum Sie abgelehnt werden. Wenn das etwas komplizierter wäre als "Add the numbers", dann ist das genau *** wie es gemacht wird. Der freche Einzeiler ist nicht besser. –

+1

@AdamSmith: Leider ist das der Fall. Zu viele Python-Programmierer versuchen gerne, so viel wie möglich in eine einzige Codezeile zu stopfen ... – PearsonArtPhoto

+2

Während ich + 1 bin und im Allgemeinen stimme (wie Adam in komplizierteren Fällen sagte), * in diesem Fall * Ein 'Try-Catch' ist Overkill. Zusätzlich wird ein 'item' in einen 'int'-Aufruf eingebunden, wenn dies eigentlich nicht notwendig sein sollte. Um zu verallgemeinern, dass alle Zahlen enthalten sind, würden Sie wahrscheinlich ein' if issinstance 'machen und das' try' ablegen insgesamt. 'filter' ist so eine wunderbare kleine Funktion für genau diese Dinge, kann nicht sehen, warum du darauf gehst. –

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

Warum haben Sie Ihren falschen Code als Antwort hinzugefügt? Sie können es löschen. – Parth

+0

es funktioniert jetzt von str (Liste [i]) – user3419487

+0

Aber es wird nicht funktionieren, wenn Sie Strings abgesehen von A-N haben. Z.B. Versuchen Sie "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:]) 

Ausgang:

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

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

Warum Rekursion? das ist unnötige Overhead – Copperfield

+0

OP will Antworten für eine Prüfung - ich stelle mir vor, ein Professor wäre ziemlich beeindruckt von dieser Antwort von Studenten in einem Intro zu Programmierklasse – inspectorG4dget

+1

Ein Codeblock allein bietet keine gute Antwort. Bitte fügen Sie Erklärungen hinzu (warum löst es das Problem, wo war der Fehler usw.) –

Verwandte Themen