2010-10-27 3 views
8

Очень часто писать цикл и помнить предыдущий.Вычитание текущего и предыдущего элементов в списке

Я хочу генератор, который делает это для меня. Что-то вроде:

import operator 

def foo(it): 
    it = iter(it) 
    f = it.next() 
    for s in it: 
     yield f, s 
     f = s 

Теперь вычтите по пару.

L = [0, 3, 4, 10, 2, 3] 

print list(foo(L)) 
print [x[1] - x[0] for x in foo(L)] 
print map(lambda x: -operator.sub(*x), foo(L)) # SAME 

Выходы:

[(0, 3), (3, 4), (4, 10), (10, 2), (2, 3)] 
[3, 1, 6, -8, 1] 
[3, 1, 6, -8, 1] 
  • Что такое хорошее название для этой операции?
  • Что такое лучший способ написать это?
  • Есть ли встроенная функция, которая делает что-то подобное?
  • Попытка использовать «карту» не упростила ее. Что значит?
+0

список понимание уже тривиально просто, и это очевидно, и естественный способ сделать это. Переход от этого к гораздо более неясному «карте» предполагает, что вы слишком задумываетесь об этом. Функция генератора также проста и проста. –

+0

это похоже на http://en.wikipedia.org/wiki/Bigram, aka ngram, когда n равно 2 – sunqiang

ответ

21
[y - x for x,y in zip(L,L[1:])] 
+2

+1 Почему я не подумал об этом. Мне это очень нравится. –

+1

+1 для простоты и переносимости. – Johnsyweb

4
l = [(0,3), (3,4), (4,10), (10,2), (2,3)] 
print [(y-x) for (x,y) in l] 

Выходы: [3, 1, 6, -8, 1]

+0

Конструкция, используемая в заявлении печати, называется «пониманием списка». –

4

Recipe from iterools:

from itertools import izip, tee 
def pairwise(iterable): 
    "s -> (s0,s1), (s1,s2), (s2, s3), ..." 
    a, b = tee(iterable) 
    next(b, None) 
    return izip(a, b) 

, а затем:

>>> L = [0, 3, 4, 10, 2, 3] 
>>> [b - a for a, b in pairwise(L)] 
[3, 1, 6, -8, 1] 

[EDIT]

Кроме того, это работает (Python < 3):

>>> map(lambda(a, b):b - a, pairwise(L)) 
+0

+1 для имени попарно и составления его с помощью itertools. –

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