Добавить список каждого N-го индекса из другого списка и повторить в зависимости от количества элементов

#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)]