В следующем решении копирование любого из списков ввода не производится.
def rzip(a,b):
m = min(len(a),len(b))
for i in xrange(m):
yield a[-m+i],b[-m+i]
for a,b in (([1,2,3,4,5,6,7],[8,9,10]),
([1,2,3],[8,9,10]),
([1,2,3,4],[1,2,3,4,5,6,7,8,9,10])):
print list(rzip(a,b))
m - длина самого короткого списка, -m + 0 всегда преобразуется в индекс 0 для этого кратчайшего списка,
в то время как -m + 0 преобразуется в индекс> = 0 для самого длинного списка
результат:
[(5, 8), (6, 9), (7, 10)]
[(1, 8), (2, 9), (3, 10)]
[(1, 7), (2, 8), (3, 9), (4, 10)]
Несмотря на то, что функция rzip () не является однострочной, я думаю, что это просто, и я уверен, что это более быстрое решение
.
Редактировать
Сначала в функции rzip () выше (и eyquem1 в следующем коде) я подумал, что создание списка заархивированных элементов путем запуска из правильной позиции в каждом списке слева направо быть хорошей процедурой тоже.
В следующем коде eyquem1bis - это функция rzip () , слегка улучшенная за счет предварительного расчета начальных позиций.
Но меня заинтересовало утверждение Раймонда Хеттингера о том, что исключительное использование zip () и итератора reversed () является более ясным и быстрым решением.
Поэтому я подумал, что использование других итераторов слева направо будет лучше, чем моя функция rzip () , и я использовал iter () и islice () для записи функции eyquem2 и eyquem3 в следующем коде.
Я сравнил времена выполнения различных решений, предложенных в большинстве ответов.
import random
from time import clock
lima,limb = 20000 , 50000
a = list(range(lima))
b = list(range(limb))
random.shuffle(a)
random.shuffle(b)
A,B,C,D,E,F,G,H,I = [],[],[],[],[],[],[],[],[],
n = 10
for essays in range(100):
te = clock()
for rep in range(n):
k = min(len(a),len(b))
sam1 = list(zip(a[-k:], b[-k:]))
tref= (clock()-te)/100
A.append((clock()-te,
'Sam Hocevar, deducted normal slicing and zip'
'\nk = min(len(a),len(b))'
'\nlist(zip(a[-k:], b[-k:]))'))
te = clock()
for rep in range(n):
k = min(len(a),len(b))
sam2 = list(zip(a[len(a)-k:], b[len(b)-k:]))
tref= (clock()-te)/100
B.append((clock()-te,
'Sam Hocevar, exactly normal slicing and zip'
'\nk = min(len(a),len(b))'
'\nlist(zip(a[len(a)-k:], b[len(b)-k:]))'))
te = clock()
for rep in range(n):
fj = list(zip(a[-len(b):], b[-len(a):]))
C.append((clock()-te,
'F.J. , deducted tricky slicing and zip'
'\nlist(zip(a[-len(b):], b[-len(a):]))'))
te = clock()
for rep in range(n):
m = min(len(a),len(b))
sleep = list(zip(a[len(a)-m:],b[len(b)-m:]))
D.append((clock()-te,
'sleeplessnerd, exactly normal slicing and zip'
'\nm = min(len(a),len(b))'
'\nlist(zip(a[len(a)-m:],b[len(b)-m:]))'))
te = clock()
for rep in range(n):
m = min(len(a),len(b))
ey1 = [ (a[-m+i],b[-m+i]) for i in range(m) ]
E.append((clock()-te,
'eyquem 1, deducted normal slicing and listcomp'
'\nm = min(len(a),len(b))'
'\n[ (a[-m+i],b[-m+i]) for i in range(m) ]'))
te = clock()
for rep in range(n):
m = min(len(a),len(b))
x,y = len(a)-m , len(b)-m
ey1bis = [ (a[x+i],b[y+i]) for i in range(m)]
F.append((clock()-te,
'eyquem 1 improved, exactly normal slicing and listcomp'
'\nm = min(len(a),len(b)'
'\nx,y = len(a)-m , len(b)-m'
'\n[(a[x+i],b[y+i]) for i in range(m)]'))
te = clock()
for rep in range(n):
ita = iter(a)
itb = iter(b)
if len(b)>len(a):
for av in range(len(b)-len(a)):
itb.__next__()
else:
for av in range(len(a)-len(b)):
itb.__next__()
ey2 = list(zip(ita,itb))
G.append((clock()-te,
'eyquem 2, use of zip and iterator iter'
'\nlist(zip(ita,itb))'))
from itertools import islice
te = clock()
for rep in range(n):
if len(b)>len(a):
ey3 = list(zip(iter(a) , islice(b,len(b)-len(a),None)))
else:
ey3 = list(zip(islice(a,len(a)-len(b),None),iter(b)))
H.append((clock()-te,
'eyquem 3, use of zip and iterators iter AND islice'
'\nlist(zip(iter(a),islice(b,len(b)-len(a),None)))'))
te = clock()
for rep in range(n):
ray = list(reversed(list(zip(reversed(a),reversed(b)))))
I.append((clock()-te,
'Raymond Hettinger, use of zip and iterator reversed'
'\nlist(reversed(list(zip(reversed(a),reversed(b)))))'))
print( 'len(a) == %d\nlen(b) == %d\n' % (len(a),len(b)) )
tempi = [min(x) for x in (A,B,C,D,E,F,G,H,I)]
tempi.sort(reverse=True)
tref = tempi[0][0]/100
print( '\n\n'.join('%.2f %% %s' % (t/tref,ch) for t,ch in tempi) )
print('\nsam1==sam2==fj==sleep==ey1==ey1bis==ey2==ey3==ray is ',sam1==sam2==fj==sleep==ey1==ey1bis==ey2==ey3==ray)
Результат со списками очень разных длин:
len(a) == 20000
len(b) == 50000
100.00 % Sam Hocevar, exactly normal slicing and zip
k = min(len(a),len(b))
list(zip(a[len(a)-k:], b[len(b)-k:]))
99.80 % Sam Hocevar, deducted normal slicing and zip
k = min(len(a),len(b))
list(zip(a[-k:], b[-k:]))
98.02 % sleeplessnerd, exactly normal slicing and zip
m = min(len(a),len(b))
list(zip(a[len(a)-m:],b[len(b)-m:]))
97.98 % F.J. , deducted tricky slicing and zip
list(zip(a[-len(b):], b[-len(a):]))
82.30 % eyquem 2, use of zip and iterator iter
list(zip(ita,itb))
69.61 % eyquem 1, deducted normal slicing and listcomp
m = min(len(a),len(b))
[ (a[-m+i],b[-m+i]) for i in range(m) ]
67.62 % eyquem 1 improved, exactly normal slicing and listcomp
m = min(len(a),len(b)
x,y = len(a)-m , len(b)-m
[(a[x+i],b[y+i]) for i in range(m)]
61.23 % eyquem 3, use of zip and iterators iter AND islice
list(zip(iter(a),islice(b,len(b)-len(a),None)))
60.92 % Raymond Hettinger, use of zip and iterator reversed
list(reversed(list(zip(reversed(a),reversed(b)))))
sam1==sam2==fj==sleep==ey1==ey1bis==ey2==ey3==ray is True
Результат с двумя списками одинаковой длины:
len(a) == 49500
len(b) == 50000
100.00 % Sam Hocevar, deducted normal slicing and zip
k = min(len(a),len(b))
list(zip(a[-k:], b[-k:]))
99.39 % F.J. , deducted tricky slicing and zip
list(zip(a[-len(b):], b[-len(a):]))
99.12 % sleeplessnerd, exactly normal slicing and zip
m = min(len(a),len(b))
list(zip(a[len(a)-m:],b[len(b)-m:]))
98.10 % Sam Hocevar, exactly normal slicing and zip
k = min(len(a),len(b))
list(zip(a[len(a)-k:], b[len(b)-k:]))
69.91 % eyquem 1, deducted normal slicing and listcomp
m = min(len(a),len(b))
[ (a[-m+i],b[-m+i]) for i in range(m) ]
66.54 % eyquem 1 improved, exactly normal slicing and listcomp
m = min(len(a),len(b)
x,y = len(a)-m , len(b)-m
[(a[x+i],b[y+i]) for i in range(m)]
58.94 % Raymond Hettinger, use of zip and iterator reversed
list(reversed(list(zip(reversed(a),reversed(b)))))
51.29 % eyquem 2, use of zip and iterator iter
list(zip(ita,itb))
51.17 % eyquem 3, use of zip and iterators iter AND islice
list(zip(iter(a),islice(b,len(b)-len(a),None)))
sam1==sam2==fj==sleep==ey1==ey1bis==ey2==ey3==ray is True
Я заключаю, что существует 3 группы решений:
решения Сэма Хочевара, FJ и sleeplessnerd имеют самые длинные исполнения.
Они используют разные комбинации нарезки и функции zip ().
Кстати, решение Сэма, одобренное в подавляющем большинстве случаев, самое длинное.
my function rzip () и rzip () - улучшенное выполнение за 68% времени, затраченного теми, кто находится в вышеуказанной группе.
Они используют только понимание списка элементов, полученных по их индексам
мои растворы eyquem2 и eyquem3, а также раствор Рэймонда Хеттингера занимают менее 61% указанного времени.
Они используют итераторы.
Время выполнения моих решений зависит от длины списка:
для списков аналогичной длины решения eyquem2 и eyquem3 имеют времена выполнения, разделенные на 2!
Но для очень разных списков eyquem2 неожиданно занимает целых 82% от эталонного времени.
Постоянное время исполнения около 60% контрольного времени решения Раймонда Хеттингера подтверждает его претензию.
Мое решение eyquem3 с iter () и islice () тоже не так уж и плохо, но не так ясно, как у Рэймонда Хеттингера, хотя последнее слишком мало Первый взгляд.