Python 列表推导返回列表的边缘值

5 投票
3 回答
508 浏览
提问于 2025-04-15 21:37

如果我在Python中有一个列表,比如说:

stuff = [1, 2, 3, 4, 5, 6, 7, 8, 9]

这个列表的长度是n(在这个例子中是9),我想创建长度为n/2(在这个例子中是4)的列表。我想要从原始列表中获取所有可能的n/2个值的组合,比如:

[1, 2, 3, 4], [2, 3, 4, 5], ..., [9, 1, 2, 3]  

有没有什么列表推导的代码可以用来遍历这个列表,并找出所有这些子列表?我不在乎列表中值的顺序,我只是想找到一种聪明的方法来生成这些列表。

3 个回答

3

可以使用 itertools.permutations() 或者 itertools.combinations(),具体用哪个取决于你是否想要像 [1,2,3,4][4,3,2,1] 这样的排列(也就是说,顺序是否重要)。你还可以加一个可选的第二个参数来指定组合的长度。

stuff = [1, 2, 3, 4, 5, 6, 7, 8, 9]

itertools.permutations(stuff, 4) # will return all possible lists of length 4
itertools.combinations(stuff, 4) # will return all possible choices of 4 elements

这里假设你并不只想要相邻的元素。

更新

因为你说你不在乎顺序,所以你可能需要使用 itertools.combinations()

5

你需要的是来自 itertools库的组合函数
(补充说明:如果顺序很重要,就用排列函数)

请注意,这个函数在Python 2.5中是没有的。如果你用的是这个版本,可以从上面的链接复制代码:

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = range(r)
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)

然后

stuff = range(9)
what_i_want = [i for i in combinations(stuff, len(stuff)/2)]
5
>>> stuff = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
>>> n=len(stuff)
>>>
>>> [(stuff+stuff[:n/2-1])[i:i+n/2] for i in range(n)]
[[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9, 1], [8, 9, 1, 2], [9, 1, 2, 3]]
>>>

注意: 上面的代码是根据你提供的例子假设的

[1, 2, 3, 4], [2, 3, 4, 5], ..., [9, 1, 2, 3]  

如果你真的需要所有可能的值,你需要使用itertools库里的permutations(排列)或combinations(组合)函数,正如其他人所建议的那样。

撰写回答