使用另一个列表中的元素对列表进行分组

时间:2019-11-01 17:21:33

标签: python python-3.x

我想使用另一个列表中出现的元素对列表进行连续分组。

例如,

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

应该有一种pythonic的方法,但是我在编码时遇到了麻烦。

此外,我在互联网上四处寻找用于分组列表的不同方法,但是我发现没有一种方法可以帮助我使用按组改变的分组值对列表进行分组(如上例所示)。

有人可以帮忙吗?

4 个答案:

答案 0 :(得分:4)

使用迭代器:

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

答案 1 :(得分:3)

您也可以使用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)]

答案 2 :(得分:1)

为此,您可以在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)

答案 3 :(得分:0)

您不必使用列表推导或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

我认为编写非专业人员可以理解的简单代码是很好的。