2013-02-17 2 views
3

У меня есть набор целых чисел, таких как (1, 2, 3, 4, 5), и я хочу создать набор (1*2, 2*3, 3*4, 4*5) путем умножения смежных элементов. Можно ли сделать это с помощью однострочного лайнера?Умножьте смежные элементы

ответ

10

Sh орт и сладкий. Помните, что zip работает только до кратчайшего ввода.

print tuple(x*y for x,y in zip(t,t[1:])) 
+0

+1 Я знал, что что-то пропустил! – Volatility

+0

@nneonneo @Paul Manta Не очень хорошо. '' t [1:] '' создает новый объект, '' zip (t, t [1:]) '' создает один объект больше, а '' для x, y в zip (t, t [1: ]) '' требуется распаковать каждый элемент заархивированного объекта на два идентификатора '' x'' и '' y'' – eyquem

+0

Если это имеет значение для вас, используйте 'izip' и' islice'. Распаковка в колодках дешевая, и избежать ее просто для экономии нескольких микросекунд не стоит. – nneonneo

6
>>> t = (1, 2, 3, 4, 5) 
>>> print tuple(t[i]*t[i+1] for i in range(len(t)-1)) 
(2, 6, 12, 20) 

Не самый pythonic решений, хотя.

+0

+1 Кажется достаточно хорошо. Почему это не самый Pythonic? –

+0

@PaulManta [Дело в точках] (http://stackoverflow.com/a/14917025/1907098) – Volatility

+0

@Volatility Прокомментируйте ответ Евгении. – eyquem

3

Если т Ваш кортеж:

>>> tuple(t[x]*t[x+1] for x in range(len(t)-1)) 
(2, 6, 12, 20) 

И еще одно решения с прекрасной картой:

>>> tuple(map(lambda x,y:x*y, t[1:], t[:-1])) 
(2, 6, 12, 20) 

Edit: А если вы беспокоитесь о дополнительном расходе памяти ломтиков, вы можете использовать из itertools, который будет перебирать ваш кортеж (thx @eyquem):

>>> tuple(map(lambda x,y:x*y, islice(t, 1, None), islice(t, 0, len(t)-1))) 
(2, 6, 12, 20) 
+0

Первый - основное благо. Второе не так хорошо, потому что '' t [1:] '' создает совершенно новый объект, а 't [: 1]' 'создает также совершенно новый объект: это время и память, которые могут быть неудобными если кортеж очень большой. - Первое решение - это доступ к элементам существующего кортежа, доступ к индексу очень быстрый (насколько мне известно) – eyquem

+0

@eyquem для небольших кортежей, индексирование - это все (относительно дорого) Python-вызовы, тогда как итерация, вероятно, включает в себя больше C-кода. (Cue жалоба о преждевременной оптимизации и т. Д.). И если вам действительно очень важно не копировать кортеж, вы можете использовать 'izip' и' islice'. – nneonneo

+0

@nneonneo Индексирование кортежей стоит дорого? Я хотел бы узнать больше – eyquem

2

Мне нравится recipes from itertools:

from itertools import izip, tee 

def pairwise(iterable): 
    xs, ys = tee(iterable) 
    next(ys) 
    return izip(xs, ys) 

print [a * b for a, b in pairwise(range(10))] 

Результат:

[0, 2, 6, 12, 20, 30, 42, 56, 72] 
3
tu = (1, 2, 3, 4, 5) 

it = iter(tu).next 
it() 
print tuple(a*it() for a in tu) 

Я приурочен различный код:

from random import choice 
from time import clock 
from itertools import izip 

tu = tuple(choice(range(0,87)) for i in xrange(2000)) 

A,B,C,D = [],[],[],[] 

for n in xrange(50): 

    rentime = 100 

    te = clock() 
    for ren in xrange(rentime): # indexing 
     tuple(tu[x]*tu[x+1] for x in range(len(tu)-1)) 
    A.append(clock()-te) 

    te = clock() 
    for ren in xrange(rentime): # zip 
     tuple(x*y for x,y in zip(tu,tu[1:])) 
    B.append(clock()-te) 

    te = clock() 
    for ren in xrange(rentime): #i ter 
     it = iter(tu).next 
     it() 
     tuple(a*it() for a in tu) 
    C.append(clock()-te) 

    te = clock() 
    for ren in xrange(rentime): # izip 
     tuple(x*y for x,y in izip(tu,tu[1:])) 
    D.append(clock()-te) 


print 'indexing ',min(A) 
print 'zip  ',min(B) 
print 'iter  ',min(C) 
print 'izip  ',min(D) 

результат

indexing 0.135054036197 
zip  0.134594201218 
iter  0.100380634969 
izip  0.0923947037962 

izip лучше, чем почтовый индекс: - 31%

Мое решение не так уж плохо (я не думаю, что так, кстати): -25% относительно молнии, 10% больше времени, чем чемпион izip

Я удивлен, что индексация не быстрее, чем почтовый индекс: nneonneo является правильным, застежка-молния является приемлемым

+0

Когда я изменяю 'range' на' xrange' в этой строке 'tuple (tu [x] * tu [x + 1] для x в диапазоне (len (tu) -1))' и увеличивает размер кортежа до 200 000 индексирования В 30% раз быстрее, чем на моей машине. Хотя, izip и iter являются самыми быстрыми и очень близкими. – Akavall

+0

@Akavall @nneonneo О, я был глуп, чтобы позволить '' range''. Вы правы, Akavall, это улучшается. Я сделал то же, что и вы (200 000), и я получил 16 для '' zip'', 13 для '' индексации'' и '' iter'' и 10 для '' izip''. Чем длиннее кортеж, тем хуже '' zip''. Это означает, что конструкция нового объекта '' zip'' тяжела. Тот факт, что '' izip'' остается лучшим, означает, что распаковка не занимает много времени. Однако 10 по сравнению с 13 сейчас составляют всего 23% меньше времени, а не 32 или 35%. – eyquem

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