【问题标题】:Iterating over partitions in Python在 Python 中迭代分区
【发布时间】:2014-06-29 02:06:28
【问题描述】:

我想知道(在 Python 中)迭代给定大小列表的分区的最佳方法是什么。

例如,我们有[1,2,3,4,5] 列表,我们想要k=3 分区。这样做的一个不好的方法是写:

lst = [1,2,3,4,5]
for i in range(1,len(lst)):
    for j in range(i+1, len(lst)):
        print lst[:i], lst[i:j], lst[j:]

这给了

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

但如果我以后想遍历k=4 分区,那么我将不得不添加一个级别的 for 循环嵌套,而这在运行时无法完成。理想情况下,我想写这样的东西:

for part in partitions([1,2,3,4,5], k):
    print part

有谁知道最好的方法?

【问题讨论】:

标签: python list loops iteration


【解决方案1】:

我通过写作完成了我想做的事情:

from itertools import tee, izip, combinations

def partitions(items, k):
    N = len(items)

    def pairwise(iterable):  # Taken from itertools recipies
        a, b = tee(iterable)
        next(b, None)
        return izip(a, b)

    def applyPart(part, items):
        lists = []
        for l,h in pairwise([0] + part + [N]):
            lists.append(items[l:h])
        return lists

    for part in combinations(range(1, N), k - 1):
        yield applyPart(list(part), items)

【讨论】:

    【解决方案2】:

    这对于较大的列表可能有些低效,但它确实有效:

    from itertools import product, islice
    
    def partitions(seq, k):
        for c in product(xrange(1, len(seq)+1), repeat=k):
            if sum(c) == len(seq):
                it = iter(seq)
                yield [list(islice(it, x)) for x in c]
    
    for part in partitions([1,2,3,4,5], 3):
        print part
    

    输出:

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

    对于更大的列表,您需要找到所有range(1, len(sequence)+1)k 大小的子集,它们的总和等于序列的长度,然后根据它们对序列进行切片。

    相关:http://www.algorithmist.com/index.php/Coin_Change

    【讨论】:

      【解决方案3】:

      如果没有pairwise,我会使用与您相同的想法:

      from itertools import combinations
      
      def partitions(items, k):
      
          def split(indices):
              i=0
              for j in indices:
                  yield items[i:j]
                  i = j
              yield items[i:]
      
          for indices in combinations(range(1, len(items)), k-1):
              yield list(split(indices))
      

      【讨论】:

      • 不要死,但这个实现要快一点。遇到这个问题的人应该改用这个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 2018-02-16
      • 2010-12-03
      相关资源
      最近更新 更多