Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
421 views
in Technique[技术] by (71.8m points)

python - summing only the numbers contained in a list

Give a method that sums all the numbers in a list. The method should be able to skip elements that are not numbers. So, sum([1, 2, 3]) should be 6 but sum(['A', 1, 'B', 2, 3]) should also be 6. How can I accomplish this?

What I have already tried so far:

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"])
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can do this with a simple one liner:

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

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

Or, if you need it inside a function:

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

Additionally, as noted in the comments, don't use names like dict and list for your variables; *they will shadow they build-in names for the dictionary (dict) and (list) types. You'll then need to explicitly del dict, list in order to use them as intended.


But, let me explain. What filter does is here is:

a) It takes a function as its first argument:

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

and then takes every element inside the list l1 (second argument) and evaluates whether it is True or False based on the function.

b) Then, filter will essentially filter out any objects inside list l1 that are not instances of int (i.e the function returns False for them). As a result, for a list like [1, 2, 3, 'A'] filter is going to return [1, 2, 3] which will then be summed up by sum().

Some Examples:

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

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

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

Slight caveat:

As is, this doesn't sum up float values, it drops them (and any other numeric types for that case). If you need that too, simply add the float type in the lambda function as so:

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

Now, your function sums floats too:

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

Add any other types as necessary in the lambda function to catch the cases that you need.


A catch all case:

As noted by @Copperfield you can check for objects that are instances of any number by utilizing the numbers.Number abstract base class in the numbers module. This acts as a catch-all case for numeric values:

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

Simpler and a bit faster, too:

Additionally, as noted by @ShadowRanger, and since lambda might not be the most comfortable construct for new users, one could simply use a generator expression (which is also faster) with sum to get the same exact result:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...