Переменная Numpy Reshaping - PullRequest
0 голосов
/ 29 марта 2019

В Python у меня есть список значений, которые мне нужно разбить на меньшие массивы, основанные на значениях в другом массиве. Например, у меня есть этот массив цифр:

[6,5,3,1,4,3,2,4,1,3,6,1]

И мне нужно, чтобы он превратился в этот массив:

[[6,5,3],[1,4],[3,2],[4],[1,3,6],[1]]

Учитывая, что у меня есть этот массив, указывающий длины разбитых частей:

[3,2,2,1,3,1]

Я попытался просмотреть документацию по измененной форме, и эта функция, кажется, делает то, что я хочу, но я не уверен, как заставить ее работать, не изменяя весь массив и делая это по существу «переменным» способом. Я также пытался сделать это для циклов, но не могу заставить индексы работать правильно.

Ответы [ 4 ]

1 голос
/ 29 марта 2019

Если вы не хотите нести дополнительные расходы по удалению элементов из списка, вот один из способов сделать это, используя itertools.islice():

iterator = iter(my_list)
my_result = [list(islice(iterator, length)) for length in my_lens]

Тестирование:

from itertools import islice

my_list = [6,5,3,1,4,3,2,4,1,3,6,1]
my_lens = [3,2,2,1,3,1]

iterator = iter(my_list)
my_result = [list(islice(iterator, length)) for length in my_lens]
print(my_result)

Выход:

[[6, 5, 3], [1, 4], [3, 2], [4], [1, 3, 6], [1]]
0 голосов
/ 29 марта 2019

Решение с использованием генератора приведено ниже.

def splitter(arr, lengths):
    assert(sum(lengths) == len(arr))
    i, s = 0, 0
    for l in lengths:
        s = s + l
        yield arr[i:s]
        i = i + l

Это обеспечивает немного большую гибкость - входная информация может быть практически любой последовательности (список, кортеж, строка, ...), а выходной может быть приведенв любой подходящей последовательности.

my_list = [6, 5, 3, 1, 4, 3, 2, 4, 1, 3, 6, 1]
my_lens = [3, 2, 2, 1, 3, 1]

ans = [x for x in splitter(my_list, my_lens)]
print(ans)
# [[6, 5, 3], [1, 4], [3, 2], [4], [1, 3, 6], [1]]

text = 'a quick brown fox jumped over the lazy dog'
lengths = [2, 6, 6, 4, 7, 5, 4, 5, 3]
print([x for x in splitter(text, lengths)])
# ['a ', 'quick ', 'brown ', 'fox ', 'jumped ', 'over ', 'the ', 'lazy ', 'dog']

my_tuple = (6, 5, 3, 1, 4, 3, 2, 4, 1, 3, 6, 1)
my_lens = [3, 2, 2, 1, 3, 1]
print(tuple(x for x in splitter(my_tuple, my_lens)))
# ((6, 5, 3), (1, 4), (3, 2), (4,), (1, 3, 6), (1,))
0 голосов
/ 29 марта 2019

Если вам нужно выполнить эту процедуру для многих списков, было бы неплохо иметь готовую функцию.Вот один из них, полностью написанный с использованием HigherOrderPython.

from itertools import accumulate, tee, chain
from operator import itemgetter

i2, i3 = tee(accumulate([3, 2, 2, 1, 3, 2]))
slicer = itemgetter(*map(slice, chain([None], i2), i3))

>>> print(slicer([6, 5, 3, 1, 4, 3, 2, 4, 1, 3, 6, 1]))
([6, 5, 3], [1, 4], [3, 2], [4], [1, 3, 6], [1])
0 голосов
/ 29 марта 2019

Предполагая, что сумма длин всегда равна длине списка, вы можете использовать list.pop(0):

l = [6,5,3,1,4,3,2,4,1,3,6,1]
[[l.pop(0) for _ in range(i)] for i in [3,2,2,1,3,1]]

Выход:

[[6, 5, 3], [1, 4], [3, 2], [4], [1, 3, 6], [1]]

Примечание: list.pop по умолчанию отображает элемент последний , поэтому используется list.pop(0).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...