Подтвердить что ты не робот

Преобразовать плоский список в список списков в Python

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

В numpy вы можете сделать что-то вроде:

>>> a=numpy.arange(9)
>>> a.reshape(3,3)
>>> a
array([[0, 1, 2],
   [3, 4, 5],
   [6, 7, 8]])

Мне было интересно, как вы поступите наоборот, и мое обычное решение выглядит примерно так:

>>> Mylist
['a', 'b', 'c', 'd', 'e', 'f']
>>> newList = []
for i in range(0,len(Mylist),2):
...     newList.append(Mylist[i], Mylist[i+1])
>>> newList 
[['a', 'b'], ['c', 'd'], ['e', 'f']]

Есть ли более "питонический" способ сделать это?

4b9b3361

Ответ 1

>>> l = ['a', 'b', 'c', 'd', 'e', 'f']
>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd'), ('e', 'f')]

Как было указано в @Lattyware, это работает только в том случае, если в каждом аргументе есть количество элементов в функции zip каждый раз, когда он возвращает кортеж. Если один из параметров имеет меньше предметов, чем другие, элементы обрезаются, например.

>>> l = ['a', 'b', 'c', 'd', 'e', 'f','g']
>>> zip(*[iter(l)]*2)
[('a', 'b'), ('c', 'd'), ('e', 'f')]

Если это так, то лучше использовать решение @Sven Marnach

Как работает zip(*[iter(s)]*n)

Ответ 2

Это обычно делается с использованием рецепта grouper из itertools documentation:

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

Пример:

>>> my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> list(grouper(2, my_list))
[('a', 'b'), ('c', 'd'), ('e', 'f'), ('g', None)]

Ответ 3

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

>>>MyList = ['a','b','c','d','e','f']
# Calculate desired row/col
>>>row = 3
>>>col = 2
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
>>>NewList
[['a', 'b', 'c'], ['d', 'e', 'f']]

Этот метод может быть расширен для создания любого размера строки и столбца. Если вы выберете значения строк и столбцов, такие как row*col >len(MyList), то подстрока (строка), содержащая последнее значение в MyList, закончится там, а NewList будет просто заполнена соответствующим количеством пустых списков, чтобы удовлетворить строке /col

>>>MyList = ['a','b','c','d','e','f','g','h']
>>>row = 3
>>>col = 3
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
>>>NewList
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g','h']]

>>>row = 4
>>>col = 4
>>>NewList = [MyList[col*i : col*(i+1)] for i in range(row)]
[['a', 'b', 'c', 'd'], ['e', 'f', 'g','h'], [], []]

Ответ 4

Если вы предпочитаете список списков, а не список кортежей из плоского списка, тогда можно сделать это:

    a = range(20) # sample starting list 
    b = [] # new list
    c = [] # alternate new list
    # ny is length of new list. nx length of each list within it
    nx = 5; ny = 4 
    bb = 0; ee = bb + nx # option one: sliding indeces for slices.
    for ii in range(ny-1):
        bb += nx
        ee += nx
        b.append(a[bb:ee])
        c.append(a[slice(ii*nx,nx*(ii+1))]) # option two, use slice()

(Я играл со сжатием целых циклов в одну строку со списком, но не был успешным, так как я использовал его, slice() может почти доставить вас туда.) Одно из возможных преимуществ этих подходов в отношении упомянутых других заключается в том, что если ваш первоначальный, плоский список не является даже кратным размерам вашего нового, нужного списка списков, вы не потеряете никаких данных. Суть в том, что последний список будет короче всех остальных, так как он будет содержать "остатки". ни один из этих методов не кажется мне очень питоновым.