2016-01-11 3 views
10

Дайте метод, который суммирует все числа в 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"]) 
+0

Заменить 'список [I] .str' с' Str (список [I]) '. – Delgan

+1

Звучит как домашнее задание для меня. –

+0

@ JonasGröger Он отправил код, который он написал, я думаю. – Delgan

ответ

17

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

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 делает здесь:

а) Он принимает функцию в качестве первого аргумента:

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

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

б) Затем 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)) 

Simpler и немного быстрее, тоже:

Кроме того, как отметил @ShadowRanger, и с тех пор lambda might not be the most comfortable construct for new users, можно было бы просто использовать a generator expression (который также быстрее) с sum, чтобы получить тот же самый точный результат:

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

, чтобы включить каждый числовой тип без упоминания каждого из них, вы можете использовать соответствующий [ABC] (https://docs.python.org/3/library/numbers.html), например 'isinstance (item, numbers.Number) ' – Copperfield

+3

Если вам понадобится' lambda' для использования 'map' /' filter', вы можете просто использовать выражение генератора (или list comp); вы ничего не получаете ни по краткости, ни по скорости, как только прибегаете к 'lambda' с' map'/'filter'. – ShadowRanger

+0

В этом контексте потеря скорости небезопасна, но существует, тем не менее, я отредактирую свой asnwer, чтобы включить генератор на основе 'sum', так как он также наиболее явный. Самая большая потеря здесь, вероятно, связана с тем, что «лямбда» является нечетной конструкцией и запутывает людей, особенно новых гостей. –

4

использование фильтра и isinstance как этот

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

Лучший ответ. Возможно, использование фильтра() будет более явным. – felipsmartins

+2

'filter' на самом деле только« лучше », когда он получает что-то на скорости или краткости (и это только увеличивает скорость, когда вы можете передать ему встроенную функцию, реализованную в C на CPython).Для чего-то вроде выражения генератора лучше всего (то же самое, что и текущий ответ, но без скобок, которые создают понимание 'list', что означает, что промежуточные' list 'не создаются и не отбрасываются); он не более или менее явный и, вероятно, немного быстрее. – ShadowRanger

10

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

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

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

+4

Не знаете, почему вас проголосовали. Если это было что-то более сложное, чем «Добавить числа», то это *** точно *** как это сделать. Навязчивый лайнер не лучше. –

+1

@AdamSmith: К сожалению, это так. Слишком много программистов на Python любят пытаться максимально втиснуть в одну строку кода ... – PearsonArtPhoto

+2

Хотя я + 1'd и вообще согласен (как сказал Адам в более сложных случаях), * в этом случае * «try-catch» является излишним. Кроме того, вы вызываете «элемент» в вызове 'int', когда это действительно не нужно, и, чтобы обобщить, чтобы охватить все числа, вы, вероятно, сделаете' if isinstance' и сбросите 'try' в целом. 'filter' - такая замечательная небольшая функция для именно этих вещей, не могу понять, почему вы на нее навязываете. –

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

Почему вы добавили неправильный код в качестве ответа? Вы можете удалить его. – Parth

+0

теперь работает str (list [i]) – user3419487

+0

Но это не сработает, если у вас есть строки, отличные от A-N. Например. Попробуйте «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:]) 

Выход:

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

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

Почему рекурсия? это лишние накладные расходы – Copperfield

+0

OP хочет получить ответы на экзамен. Я полагаю, что профессор будет очень впечатлен этим ответом от ученика во вступлении к классу программирования – inspectorG4dget

+1

Один только код не дает хорошего ответа. Пожалуйста, добавьте объяснения (почему он решает проблему, где была ошибка и т. Д.) –

Смежные вопросы