我想从列表中生成组合而不考虑相邻元素。
我尝试过一种代码,该代码提供了不考虑相邻元素的组合,并且可以处理列表中的唯一元素。 但是,它不适用于列表Eg中的重复元素。 [4,5,4,3]
代码:
import itertools
b = []
stuff = [4,5,4,3]
for L in range(2, len(stuff)+1):
for subset in itertools.combinations(stuff, L):
a =list(subset)
for i in range(1,len(a)):
if stuff.index(a[i-1]) == stuff.index(a[i])-1:
a.clear()
break
else:
b.append(a)
print('b = ',b)
预期结果= [[4,4],[4,3],[5,3]]
实际结果= [[4, 4], [4, 3], [5, 4], [5, 3], [4, 3], [4, 4, 3], [4, 4, 3], [5, 4, 3], [5, 4, 3]]
我可以举一个例子来解释:假设列表是[1,2,3,4,5],那么可能的非相邻组合是[[1,3],[1,4],[1,5], [2,4],[2,5],[3,5],[1,3,5]。我想要这些组合。我正在尝试的代码可以与唯一集一起很好地工作,但是当给定列表中的数字重复出现时,例如[1,3,2,3,2,5],那么在获取索引时,它总是取前3个而不是其他一。那么如何从这个集合中获得组合
答案 0 :(得分:1)
与其生成所有的itertools.combinations
,然后使用index
过滤掉有效的{a},这(a)效率很低,(b)不适用于重复的元素,而是应该实现自己的combinations
算法,这一点也不难,可能看起来像这样:
def comb(lst, num):
if num == 0:
yield []
if 0 < num <= len(lst):
first, *rest = lst
for c in comb(rest, num-1):
yield [first] + c
for c in comb(rest, num):
yield c
要添加“无相邻元素”约束,只需跟踪您是否获取了最后一个元素,并且仅在情况并非如此的情况下才添加下一个元素:
def comb_no_adj(lst, num, last=False):
if num == 0:
yield []
if 0 < num <= len(lst):
first, *rest = lst
if not last:
for c in comb_no_adj(rest, num-1, True):
yield [first] + c
for c in comb_no_adj(rest, num, False):
yield c
comb_no_adj([1,2,3,4,5,6], 3)
的示例组合为[1, 3, 5], [1, 3, 6], [1, 4, 6], [2, 4, 6]
(此示例不包含重复项,只是为了易于理解;因为该算法未使用{{ 1}},重复元素不是问题。)
更新:实际上,首先生成 all 个组合,然后过滤无效的不起作用。请考虑以下示例:index
。具有两个元素的所有组合均为[1,1,1]
(第一和第二,第一和第三,第二和第三[1,1], [1,1], [1,1]
)。您将如何决定保留哪些和丢弃哪些?对于1
,情况变得更糟。 (虽然您可以生成所有元素-索引对组合,然后对其进行过滤,但是由于大量组合将被过滤掉,所以效率仍然较低。)>