#python
#python
Вопрос:
Можете ли вы сделать это более питоническим, используя функции map и / или reduce? она просто суммирует произведения каждой последовательной пары чисел.
topo = (14,10,6,7,23,6)
result = 0
for i in range(len(topo)-1):
result = topo[i]*topo[i 1]
Ответ №1:
Это самый приятный способ, который я могу придумать:
import operator
sum(map(operator.mul, topo[:-1], topo[1:]))
Редактировать: я только что узнал, что есть лучший способ сделать это:
import operator
import itertools
def pairwise(iterable):
a, b = itertools.tee(iterable)
next(b, None)
return a, b
def sum_products(l):
return sum(itertools.imap(operator.mul, *pairwise(l)))
Название парной функции указано в документации itertools.
Это быстрее и использует меньше памяти. Конечно, это менее лаконично.
Комментарии:
1. Просто используйте
topo
вместоtopo[:-1]
2. @Kable, это не одно и то же… topo[-1] удаляет последний элемент.
3. Хотя
topo
вместоtopo[:-1]
на Python 2 дляmap
это не сработает, сimap
fromitertools
это будет нормально работать, и я полагаю, что это также будет нормально работать на Python 3.4. agf, хотя вы можете это сделать, на самом деле это не самый ясный или кратчайший способ.
Ответ №2:
Вы можете использовать map
и reduce
подобным образом, но я не уверен, что это более питоническое:
reduce( lambda x, y: x y, map( lambda x, y: x * y, topo[:-1], topo[1:]) )
Вероятно, проще это выражение sum generator:
sum(topo[x] * topo[x 1] for x in xrange(len(topo)-1))
Комментарии:
1. Спасибо, мне нравится ваша вторая.
2. Другим способом использования
sum
было быsum(a * b for a, b in zip(topo[:-1], topo[1:]))
Ответ №3:
Это работает:
mult = lambda (x, y): x * y
pairs = zip(list(topo), list(topo)[1:])
result = sum(map(mult, pairs))
но, вероятно, это сложнее понять.
Комментарии:
1. Вместо определения
mult
простоfrom operator import mul
2. Я думаю, что на самом деле это не работает, потому что мой лямбда принимает кортеж…
3. @Ben: Просто используйте
map
с несколькими итерациями:sum(map(mul, topo[:-1], topo[1:]))
Ответ №4:
Вместо map должно работать понимание списка:
>>> topo = (14,10,6,7,23,6)
>>> sum((x*y for x,y in zip(topo[:-1],topo[1:])))
541
>>>
или
>>> sum((topo[i]*topo[i 1] for i in range(len(topo)-1)))
541
Комментарии:
1. В ответ Чарльза Бейли включено мое решение, и он на некоторое время опередил меня. Каким-то образом я пропустил это при первом просмотре ответов.
Ответ №5:
Я бы не назвал это pythonic, хотя это выглядит круче, reduce
здесь не подходит:
def func(first, *rest):
return reduce(lambda (x,y),z:(x y*z,z), rest, (0,first))[0]
Обратите внимание, что (x,y),z
используется только 2.x.
Ответ №6:
С помощью reduce и Python < 3.x:
from itertools import tee, izip
#recipe from http://docs.python.org/library/itertools.html#recipes
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
reduce(lambda s, (x, y):s x * y, pairwise(topo), 0)
с помощью map:
from operator import mul
from itertools import tee
a, b = tee(topo)
next(b, None)
sum(map(mul, a, b))
Ответ №7:
это также может дать ваш ответ
a= [14,10,6,7,23,6]
reduce(lambda a,b: a b, map(lambda (x,y): x*y, map(lambda i:(a[i],a[i 1]), range(len(a)-1)) ) )