Суммируя только числа, содержащиеся в списке

Дайте метод, который суммирует все числа в list. Метод должен иметь возможность пропускать элементы, которые не являются числами. Итак, sum([1, 2, 3]) должен быть 6, но sum(['A', 1, 'B', 2, 3]) также должен быть 6. Как я могу это сделать?

То, что я уже пробовал:

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"])

Ответ 1

Вы можете сделать это с помощью простого одного вкладыша:

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

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

Или, если вам нужно это внутри функции:

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

Кроме того, как отмечено в комментариях, не используйте для своих переменных имена типа dict и list; * они будут затенять имена встроенных имен для типов словаря (dict) и (list). Затем вам нужно явно указать del dict, list, чтобы использовать их по назначению.


Но позвольте мне объяснить. Что filter здесь:

a) В качестве первого аргумента требуется функция:

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

а затем берет каждый элемент внутри списка l1 (второй аргумент) и оценивает, является ли он True или False на основе функции.

b). Затем filter по существу будет отфильтровывать любые объекты внутри списка l1, которые не являются экземплярами int (то есть функция возвращает False для них). В результате для списка, такого как [1, 2, 3, 'A'], фильтр вернет [1, 2, 3], который затем будет суммирован sum().

Некоторые примеры:

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

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

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

Незначительное предупреждение:

Как и в этом случае, это не суммирует значения float, оно отбрасывает их (и любые другие числовые типы для этого случая). Если вам это нужно, просто добавьте тип float в функцию lambda так:

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

Теперь ваша сумма сумм тоже плавает:

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

Добавьте любые другие типы, если необходимо, в функцию lambda, чтобы поймать нужные вам случаи.


Ухватить весь случай:

Как отмечено @Copperfield, вы можете проверить объекты, являющиеся экземплярами любого числа, используя numbers.Number абстрактный базовый класс в модуле numbers. Это действует как регистр для числовых значений:

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

Упростить и немного быстрее:

Кроме того, как отмечено @ShadowRanger, и поскольку lambda может быть не самой удобной конструкцией для новых пользователей, можно просто использовать выражение генератора (которое также быстрее) с sum, чтобы получить тот же точный результат:

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

Ответ 2

Пути Pythonic - это попытка try/except. Хотя вы можете сделать это в одном лайнере, я предпочитаю немного разобраться, чтобы увидеть, что именно происходит.

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

Если вы хотите включить плавающие точки, просто измените int на a float. Плавающие точки - это что-нибудь с десятичной точкой, среди прочих.

Ответ 3

sum([x for x in list if isinstance(x, (int, long, float))])

Ответ 4

Использовать фильтр и isinstance, как это

>>> test = [1,2,3,4,5,6,"A","B"]
>>> sum(filter(lambda x:isinstance(x,int),test))
21
>>> 

Ответ 5

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"])

Ответ 6

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

Вывод:

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

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