给定一个列表(或Java,我试图在两种语言中都这样做),我怎么能得到所有不同的方式来分割一个列表到不同的分组,因为每个分组必须至少有一定的大小?我认为获得拆分地点的组合是最好的方式。如何获得至少一定大小的列表分组的所有组合?
列表和最小尺寸的示例输入是
[1,2,3], 2
和相应的输出应是
[[1,2], [1,3], [2,3], [1,2,3]]
给定一个列表(或Java,我试图在两种语言中都这样做),我怎么能得到所有不同的方式来分割一个列表到不同的分组,因为每个分组必须至少有一定的大小?我认为获得拆分地点的组合是最好的方式。如何获得至少一定大小的列表分组的所有组合?
列表和最小尺寸的示例输入是
[1,2,3], 2
和相应的输出应是
[[1,2], [1,3], [2,3], [1,2,3]]
编辑
基于OP的新的输入/输出要求,它只是几行:
def groupings(lst, min_size):
results = [tuple(lst)]
for i in range(min_size, len(lst)):
results.extend(combinations(lst, i))
return results
ORIGINAL
(基于不正确的假设,OP通缉给定最小分区大小的所有可能的分区)。
所以itertools.combinations()应该是一个起点。例如,
>>> list(combinations('ABCD', 2))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
这样就给出了一个答案。您的分组与最小大小设置为2“ABCD”的输出是:
[['A', 'B', 'C', 'D']]
[['A', 'D'], ['B', 'C']]
[['A', 'C'], ['B', 'D']]
[['A', 'B'], ['C', 'D']]
所以高层次的过程应该是大致为:
results = []
remaining = [([], list)] # Start without any groups and the full list
while remaining not empty:
groups, list = remaining.pop()
if len(list) >= min_size:
results.append(groups + list)
for size in min_size to len(list) - 1:
for combo in combinations:
new <- (groups + combo, list - combo)
if new will not cause duplicates:
remaining.append(new)
下面是一些代码,似乎工作。为了避免重复,并处理原始列表可能有重复的情况,我修改了itertools.combinations中的代码,而不仅仅是使用方法。
def groupings(lst, min_size):
lst = list(lst)
# List for storing our final groupings
results = []
# Unfinished grouping, tuple storing the group and remaining sub-list
# Initialize with the empty group and original list
remaining = [([], lst)]
# Continue as long as we have unfinished groupings
while len(remaining):
# Get an unfinished grouping
current_group, current_lst = remaining.pop()
n = len(current_lst)
# If the last part of the list is big enough,
# then record the grouping
if n >= min_size:
results.append(current_group + [current_lst])
# Otherwise, discard it
else:
continue
# Helper set for getting remainder below
all_indices = set(range(n))
# Iterate the group length from min_size to the length of our current list
for r in range(min_size, n - 1):
# This is a modified version of itertools.combinations()
# http://docs.python.org/3.3/library/itertools.html#itertools.combinations
# Add the first combination to our remaining list
indices = list(range(r))
remainder = current_lst[r:]
group = current_group + [current_lst[:r]]
remaining.append((group, remainder))
while True:
for i in reversed(range(r)):
if indices[i] != i + n - r:
break
else:
break
indices[i] += 1
for j in range(i+1, r):
indices[j] = indices[j-1] + 1
# If one of the remaining indexes is less than the minimum used index,
# then a different iteration will handle it, so discard this one
min_index = min(indices)
remainder = []
for i in all_indices.difference(indices):
remainder.append(current_lst[i])
if i < min_index:
break
else:
# Add this combination to our remaining list
group = current_group + [[current_lst[i] for i in indices]]
remaining.append((group, remainder))
return results
结果:
>>> groupings('ABCDE', 2)
[['A', 'B', 'C', 'D', 'E']]
[['A', 'D', 'E'], ['B', 'C']]
[['A', 'C', 'E'], ['B', 'D']]
[['A', 'C', 'D'], ['B', 'E']]
[['A', 'B', 'E'], ['C', 'D']]
[['A', 'B', 'D'], ['C', 'E']]
[['A', 'B', 'C'], ['D', 'E']]
[['A', 'E'], ['B', 'C', 'D']]
[['A', 'D'], ['B', 'C', 'E']]
[['A', 'C'], ['B', 'D', 'E']]
[['A', 'B'], ['C', 'D', 'E']]
在Python,可以做到这一点递归:
def partition(lst, minsize=1):
yield [lst]
for n in range(minsize, len(lst)-minsize+1):
for p in partition(lst[n:], minsize):
yield [lst[:n]] + [l for l in p]
例如:
>>> lst = [1, 2, 3, 4, 5, 6, 7]
>>> partition(lst, 3)
[[[1, 2, 3, 4, 5, 6, 7]],
[[1, 2, 3], [4, 5, 6, 7]],
[[1, 2, 3, 4], [5, 6, 7]]]
>>> list(partition(lst, 2))
[[[1, 2, 3, 4, 5, 6, 7]], [[1, 2], [3, 4, 5, 6, 7]],
[[1, 2], [3, 4], [5, 6, 7]], [[1, 2], [3, 4, 5], [6, 7]],
[[1, 2, 3], [4, 5, 6, 7]], [[1, 2, 3], [4, 5], [6, 7]],
[[1, 2, 3, 4], [5, 6, 7]], [[1, 2, 3, 4, 5], [6, 7]]]
请看我上面的评论,为什么这不是我想要完成的。我的问题还不够清楚。 – bab
那么你能否编辑这个问题来准确地描述你想要达到的目标,例如样本输入和输出。 – jonrsharpe
你能对你的要求更具体的每个 “分组”?例如,给定大小为[1,2,3,4,5,6,7]的[[1,2,5,6],[3,4,7]]是有效的?还是每个组都需要它的元素在原始列表中彼此相邻? –
我不好意思,我甚至没有意识到接受的答案没有完成这个。是的,我试图找出如何获得所有可能的组合组合,因此每个组不需要其元素彼此相邻。 – bab
您正试图枚举给定集合的至少给定大小的所有子集。我在谈论子集,因为在这里命令显然是不重要的,我假设你不能有重复(你可以,但可能会是一个multiset,使事情变得复杂)。这是一个典型的递归问题。由于阈值的下限,因此您可以从完整集合开始,一次删除一个元素,然后在小的子集上进行递归,而大小足够大。 –