Я пытаюсь объединить 2 списка, которые имеют разные данные и размер в 1, и имеют меньший список "обернуть" вокруг. Я ищу чистый способ сделать это, например,

Вход:

list1 = ['apple', 'orange', 'strawberry', 'avocado']
list2 = ['1','2','3']

Выход:

[ 
    {"l1": "apple", "l2": "1"}, 
    {"l1": "orange", "l2": "2"}, 
    {"l1": "strawberry", "l2": "3"}, 
    {"l1": "avocado", "l2": "1"}
 ]

Обратите внимание, что для "avocado" мы вернулись к "1" и обернули список list2.

Очевидное (и уродливое) решение состоит в том, чтобы просто начать с пустого списка, иметь 2 индекса в цикле, каждая итерация добавляет новый элемент списка, а меньший «оборачивает» начало, когда достигает конца. Есть ли чистый способ сделать это в Python 2.7?

1
Jack T. 29 Авг 2017 в 01:15

4 ответа

Лучший ответ

Вы можете использовать itertools.cycle, чтобы обернуть второй список :

from itertools import cycle

lst = [dict(zip(['l1', 'l2'], tup)) for tup in zip(list1, cycle(list2))]
6
Moses Koledoye 28 Авг 2017 в 22:18
def processing(opt, longlist, shortlist):
  def processing_iter(inL, refL, outL):
    if refL == []:
      return outL
    elif inL == []:
      return processing_iter(shortlist, refL[1:], outL+opt(refL[0], shortlist[0]))
    else:
      return processing_iter(inL[1:], refL[1:], outL+opt(refL[0], inL[0]))
  return processing_iter(shortlist, longlist, [])


def makedict(a,b): return [{"l1":a, "l2":b}]

list1 = ['apple', 'orange', 'strawberry', 'avocado']
list2 = ['1','2','3']
print(processing(makedict,list1, list2))
0
englealuze 29 Авг 2017 в 14:28

Вы можете просто использовать enumerate для простоты; однако более чистое решение будет включать itertools.cycle:

list1 = ['apple', 'orange', 'strawberry', 'avocado']
list2 = ['1','2','3']
new_list = [{"li":a, "l2":list2[i%len(list2)]} for i, a in enumerate(list1)]

Выход:

[{'l2': '1', 'li': 'apple'}, {'l2': '2', 'li': 'orange'}, {'l2': '3', 'li': 'strawberry'}, {'l2': '1', 'li': 'avocado'}]
2
Ajax1234 28 Авг 2017 в 22:24

Вы можете использовать генератор, который избегает добавления в пустой список:

def func(l1, l2):
    length1 = len(l1)
    length2 = len(l2)
    for idx in range(max(length1, length2)):
        # I use the modulo so the indices wrap around.
        yield {'l1': l1[idx % length1], 'l2': l2[idx % length2]}

list(func(list1, list2))
# [{'l1': 'apple', 'l2': '1'},
#  {'l1': 'orange', 'l2': '2'},
#  {'l1': 'strawberry', 'l2': '3'},
#  {'l1': 'avocado', 'l2': '1'}]

Однако itertools.cycle (см. Другой ответ), вероятно, намного лучше.

2
MSeifert 28 Авг 2017 в 22:18