【问题标题】:Algorithm to generate (not quite) spanning set in Python在 Python 中生成(不完全)跨越集的算法
【发布时间】:2012-02-29 09:41:55
【问题描述】:

这是从这个问题开始的:

Algorithm to generate spanning set

给定这个输入:[1,2,3,4]

我想在 python 中生成这组集合:

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

所以和上一个问题不同的是,列表的顺序是保留的。

理想情况下,该代码适用于列表中的 n 个项目

非常感谢

编辑 2:如果原始输入是字符串而不是列表(字符串中的每个单词都成为列表中的一个项目),任何人都可以建议我如何执行此操作。谢谢!

编辑:添加 [1] [2, 3, 4] 抱歉,错误

【问题讨论】:

  • 你忘了设置 [1] [2,3,4] 吗?
  • 为什么输出中没有[1], [2, 3, 4]
  • 你想要做的是类似于问题Python: show all possible groupings of a list的第1部分。
  • 有点像这样。虽然我希望概括为将列表分成“最多 n”部分

标签: python algorithm


【解决方案1】:

您可能还喜欢递归解决方案:

def span(lst):
  yield [lst]
  for i in range(1, len(lst)):
    for x in span(lst[i:]):
      yield [lst[:i]] + x

说明

我们在这里利用递归来解决问题。方法如下:

对于每个列表,整个列表都是有效的跨度:[1,2,3,4] => [[1,2,3,4]]

对于每个长度超过1 的列表,我们可以将第一个项目作为一个组,然后对剩余的列表应用相同的算法以获得所有组合结果:

[1,2,3] => 
  [[1]] + [[2], [3]]  # => [[1], [2], [3]]
  [[1]] + [[2,3]]     # => [[1], [2,3]]

对于每个长度大于2 的列表,我们也可以将前 两个 项作为一个组,然后对剩余的列表应用相同的算法并组合结果:

[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]]     # => [[1,2], [3], [4,5]]
  [[1,2]] + [[3,4,5]]        # => [[1,2], [3,4,5]]

我们可以看到右侧的可能组合确实是列表其余部分的所有可能分组[3,4,5]

对于每个长于 ... 的列表等。因此,最终算法如下:

  1. yield 整个列表(它始终是有效的跨度,见上文)
  2. 对于列表的每个可能拆分,生成列表的左侧部分以及列表右侧部分的所有可能的跨度。

yield 是 Python 中的一个特殊关键字,它使函数成为 generator,这意味着它返回一个可迭代对象,可用于枚举找到的所有结果。您可以使用 list 构造函数将结果转换为列表:list(span([1,2,3,4]))

【讨论】:

  • @user1195889:如果您的问题得到解答,您可以接受其中一个答案以关闭它,方法是使用左侧的勾选按钮 :)
  • 我可以花几个小时来完成它们,然后我会这样做:)
  • @user:很公平 :) 玩得开心!
  • 您能否向新手解释一下这是如何工作的 - 只需几行散文吗?如果您没有时间,请不要担心
  • @user1195889:我添加了解释。
【解决方案2】:

调整来自Python: show all possible groupings of a list的解决方案之一:

from itertools import combinations

def cut(lst, indexes):
    last = 0
    for i in indexes:
        yield lst[last:i]
        last = i
    yield lst[last:]

def generate(lst, n):
    for indexes in combinations(list(range(1,len(lst))), n - 1):
        yield list(cut(lst, indexes))

data = [1,2,3,4]

for i in range(1, len(data)+1):  # the only difference is here
    for g in generate(data, i):
        print(g)

"""
[[1, 2, 3, 4]]
[[1], [2, 3, 4]]
[[1, 2], [3, 4]]
[[1, 2, 3], [4]]
[[1], [2], [3, 4]]
[[1], [2, 3], [4]]
[[1, 2], [3], [4]]
[[1], [2], [3], [4]]
"""

【讨论】:

  • 谢谢,这真的很有帮助
【解决方案3】:
import itertools
a = [1, 2, 3, 4]
n = len(a)
for num_splits in range(n):
    for splits in itertools.combinations(range(1, n), num_splits):
        splices = zip([0] + list(splits), list(splits) + [n])
        print([a[i:j] for i, j in splices])

打印

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

【讨论】:

  • 非常感谢,太好了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 2010-10-02
  • 2011-03-23
相关资源
最近更新 更多