#python
#python
Вопрос:
У меня есть два списка:
gizmos = [('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252),
('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252),
('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252)]
owner = ['owner1','owner3','owner32']
Моя цель — объединить оба списка в новый список как таковой. Я хочу, чтобы первый элемент повторялся N раз в зависимости от длины владельца, а затем продолжался для следующих элементов. В этом случае владелец length = 3
gizmos = [('owner1','gizmo1', 314),
('owner1','gizmo1', 18),
('owner1','gizmo1', 72),
#start appending second element from list
('owner3','gizmo1', 2),
('owner3','gizmo1', 252),
('owner3','gizmo1', 314),
#start appending third element from list
('owner32','gizmo1', 18),
('owner32','gizmo1', 72),
('owner32','gizmo1', 2)]
Я попытался zip
использовать 2 списка, но из-за несоответствия длин это не сработало.
Ответ №1:
Вы могли бы использовать рецепт grouper из itertools:
import pprint
from itertools import zip_longest
def grouper(iterable, n, fillvalue=None):
"Collect data into fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return zip_longest(*args, fillvalue=fillvalue)
res = [(o, *gizmo) for group, o in zip(grouper(gizmos, 3), owner) for gizmo in group]
pprint.pprint(res)
Вывод
[('owner1', 'gizmo1', 314),
('owner1', 'gizmo1', 18),
('owner1', 'gizmo1', 72),
('owner3', 'gizmo1', 2),
('owner3', 'gizmo1', 252),
('owner3', 'gizmo1', 314),
('owner32', 'gizmo1', 18),
('owner32', 'gizmo1', 72),
('owner32', 'gizmo1', 2)]
Комментарии:
1. я думаю, в выводе должно быть только 9 элементов?
2. Спасибо! Если бы я хотел сделать что-то вроде gizmos = [(‘owner1′,’gizmo1’, 314), (‘owner3′,’gizmo1’, 18), (‘owner32’, ‘gizmo1’, 72), (‘owner1′,’gizmo1’, 2), (‘owner3′,’gizmo1’, 252), (‘owner32’, ‘gizmo1’, 314), (‘owner1’, ‘gizmo1’, 18), (‘owner3’, ‘gizmo1’, 72), (‘owner32′,’gizmo1’, 2)] Естьспособ перебора имен владельцев?
3. @hedgethenight взгляните на cycle в itertools
4. @DaniMesejo большое вам спасибо! очень полезно
Ответ №2:
Используйте np.repeat, чтобы получить ['owner1', 'owner1', 'owner1','owner2',...]
[(x[0], *x[1]) for x in zip( *[np.repeat(owner, len(owner)), gizmos])]
[('owner1', 'gizmo1', 314),
('owner1', 'gizmo1', 18),
('owner1', 'gizmo1', 72),
('owner3', 'gizmo1', 2),
('owner3', 'gizmo1', 252),
('owner3', 'gizmo1', 314),
('owner32', 'gizmo1', 18),
('owner32', 'gizmo1', 72),
('owner32', 'gizmo1', 2)]
Если вам не нравится numpy:
sum([[x]*len(owner) for x in owner], [])
Это работает аналогично np.repeat(owner, len(owner))
Ответ №3:
Вы можете сделать это, сначала создав список, в котором владельцы повторяются <длина> раз, а затем архивируются. Например:
gizmos = [('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252),
('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252),
('gizmo1', 314),
('gizmo1', 18),
('gizmo1', 72),
('gizmo1', 2),
('gizmo1', 252)]
owner = ['owner1','owner3','owner32']
length=3
## create a list where each owner is repeated [length] times
repeated_owners = [x for x in owner for i in range(length)]
## then zip
result = [(x, *y) for x, y in zip(repeated_owners, gizmos)]
print(result)
Результат:
[('owner1', 'gizmo1', 314),
('owner1', 'gizmo1', 18),
('owner1', 'gizmo1', 72),
('owner3', 'gizmo1', 2),
('owner3', 'gizmo1', 252),
('owner3', 'gizmo1', 314),
('owner32', 'gizmo1', 18),
('owner32', 'gizmo1', 72),
('owner32', 'gizmo1', 2)]