Группировка списка с использованием элементов в другом списке - PullRequest
0 голосов
/ 01 ноября 2019

Я хотел бы последовательно сгруппировать список, используя элементы, которые появляются в другом списке.

Например,

x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
y = [2,3,1,5,6,4]

Я хотел бы сгруппировать список x, используя список y такой, что новый список, скажем, список z, будет иметь следующий вид:

z = [[0,1],[2,3,4],[5],[6,7,8,9,10],[11,12,13,14,15,16],[17,18,19,20]]

Должен существовать питонский способ сделать это, но у меня возникают проблемы с его кодированием.

Кроме того, я искал в Интернете различные методы группировки списков, но ни один из найденных мной методов не помог мне сгруппировать списки, используя значения группировки, которые меняются в зависимости от группы (как в примере выше).

Может ли кто-нибудь помочь

Ответы [ 4 ]

4 голосов
/ 01 ноября 2019

Использование итератора:

from itertools import islice

values = list(range(0, 21))
lengths = [2, 3, 1, 5, 6, 4]

values_iterator = iter(values)
lists = [list(islice(values_iterator, length)) for length in lengths]

print(lists)

Вывод:

[[0, 1], [2, 3, 4], [5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16], [17, 18, 19, 20]]
3 голосов
/ 01 ноября 2019

Вы также можете использовать itertools.accumulate

from itertools import accumulate

x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] 
y = [2,3,1,5,6,4]

z = [x[a:b] for a, b in zip(*map(accumulate,([0]+y,y)))]

Результаты:

[[0, 1], [2, 3, 4], [5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16], [17, 18, 19, 20]]

Или вы можете использовать метод itertools pairwise. Это, вероятно, более эффективно.

a, b = tee(accumulate([0]+y)); next(b, None)
z = [x[a:b] for a, b in zip(a,b)]
1 голос
/ 01 ноября 2019

Для этого вы можете использовать понимание списка более enumerate(y), где вы нарезаете x в соответствии с

  1. частичной суммой по y до текущего индекса и

  2. текущее значение

Это может выглядеть так:

x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
y = [2,3,1,5,6,4]

z = [x[sum(y[:i]):sum(y[:i])+v] for (i,v) in enumerate(y)] 

print(z)
[[0, 1], [2, 3, 4], [5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16], [17, 18, 19, 20]]

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

x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
y = [2,3,1,5,6,4]

z = [x[s:s+v] for (s,v) in [(sum(y[:i]),y[i]) for i in range(len(y))]] 

print(z)
[[0, 1], [2, 3, 4], [5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16], [17, 18, 19, 20]]

Чтобы уменьшитьСуммируя еще больше, используйте reduce, чтобы создать пары индексов для нарезки:

from functools import reduce

x = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
y = [2,3,1,5,6,4]

z = [x[s:e] for s,e in reduce(
        lambda c,x: c + [(c[-1][1], c[-1][1]+x)], 
        y[1:], 
        [(0,y[0])] 
        )]
[[0, 1], [2, 3, 4], [5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16], [17, 18, 19, 20]]
print(z)
0 голосов
/ 01 ноября 2019

Вам не нужно использовать списочные выражения или символы itertools, чтобы быть "Pythonic":

def chunk_with_variable_sizes(nums, sizes):
    result = []
    i = 0
    for size in sizes:
        part = nums[i:i+size]
        result.append(part)
        i += size

    if i != len(nums):
        raise ValueError('sizes must total len(nums)')

    return result

Я думаю, что было бы хорошо написать код, который прост и понятен неспециалистам.

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