我尝试加入两个列表并输出合并列表的所有可能组合,以维护原始两个列表的排序。例如:
DirectoryEntry dnc = new DirectoryEntry("LDAP://corp.domain.tld");
SecurityIdentifier domainSID = new SecurityIdentifier(dnc.Properties["objectSid"].Value);
string administratorsGroupSID = String.Format("{0}-544", domainSID);
string administratorsGroupSIDPath = String.Format("LDAP://<SID={0}>", administratorsGroupSID);
DirecoryEntry AdministratorsGroupDE = new DirectoryEntry(administratorsGroupSIDPath);
列表中的每个元素&#34;组合&#34;, 2 始终位于 1 之前, 9 始终位于之前的 8
到目前为止,我已经使用了来自itertools的排列来循环所有可能的排列,但它还不够快。
这是我得到的:
list_1 = [9,8]
list_2 = [2,1]
#output
combo= [9821,9281,2981,2918,2198,9218]
谢谢!
答案 0 :(得分:4)
尝试一下:
import itertools
lst1 = ['a', 'b']
lst2 = [1, 2]
for locations in itertools.combinations(range(len(lst1) + len(lst2)), len(lst2)):
result = lst1[:]
for location, element in zip(locations, lst2):
result.insert(location, element)
print(''.join(map(str, result)))
# Output:
# 12ab
# 1a2b
# 1ab2
# a12b
# a1b2
# ab12
我想到问题的方式,你从第一个序列(在这种情况下为ab
)开始,然后查找可以插入第二个序列的元素的所有可能位置(在这种情况下,一个1
,然后一个2
)。
itertools.combinations
来电为您提供了这些组合。在上面的示例中,它遍历位置(0, 1)
,(0, 2)
,(0, 3)
,(1, 2)
,(1, 3)
,(2, 3)
。
对于每组坐标,我们只需将第二个列表中的元素插入指定的索引。
<强>更新强>
这是一个处理任意数量列表的递归解决方案,基于@ĐặngXuânThành在他的回答中提出的建议:
import itertools
def in_order_combinations(*lists):
lists = list(filter(len, lists))
if len(lists) == 0:
yield []
for lst in lists:
element = lst.pop()
for combination in in_order_combinations(*lists):
yield combination + [element]
lst.append(element)
for combo in in_order_combinations(['a', 'b'], [1, 2]):
print(''.join(map(str, combo)))
基本思路是,从ab
和12
开始,您知道所有可能的解决方案都将以b
或2
结束。以b
结尾的那些都将以(a
,12
)的解决方案开头。以2
结尾的内容都将以(ab
,1
)的解决方案开头。
递归的基本情况就是没有列表时。 (我们去的时候会清空空列表。)
答案 1 :(得分:3)
如果您的输出是列表而不是连接数字,那将会更清晰,但这并不重要。这是python3中的一个简单的递归解决方案(但你可以简单地将它转换为python2)。
def combine(xs, ys):
if xs == []: return [ys]
if ys == []: return [xs]
x, *xs_tail = xs
y, *ys_tail = ys
return [ [x] + l for l in combine(xs_tail, ys) ] + \
[ [y] + l for l in combine(ys_tail, xs) ]
这将返回一个列表列表:
>>> combine([9, 8], [2, 1])
[[9, 8, 2, 1], [9, 2, 1, 8], [9, 2, 8, 1], [2, 1, 9, 8], [2, 9, 8, 1], [2, 9, 1, 8]]
以下是将其转换为所需输出的方法:
def list_to_int(digits):
return int(''.join(map(str, digits)))
def combine_flat(xs, ys):
return [list_to_int(l) for l in combine(xs, ys)]
答案 2 :(得分:2)
使用递归生成器的解决方案(yield from ...
需要Python 3):
def f(a,b,p=[]):
if len(a)==0 or len(b)==0:
yield p+a+b
else:
yield from f(a[1:],b,p+[a[0]])
yield from f(a,b[1:],p+[b[0]])
在每一步,您可以选择a
的第一个字符或b
的第一个字符,并递归地构建列表的其余部分。如果其中一个变空,则没有更多的选择点。
>>> list(f([9,8],[2,1]))
[[9, 8, 2, 1], [9, 2, 8, 1], [9, 2, 1, 8], [2, 9, 8, 1], [2, 9, 1, 8], [2, 1, 9, 8]]
更新:从上面的解决方案开始,这是一个处理任意数量列表的实现:
def f(*args,p=[]):
if any(len(arg)==0 for arg in args):
yield p+[el for arg in args for el in arg]
else:
for i,arg in enumerate(args):
args1=list(args)
args1[i]=arg[1:]
yield from f(*args1,p=p+[arg[0]])
答案 3 :(得分:1)
我不太了解python,但我有一个想法可能会有所帮助
这个想法是使用递归:
加入两个名单n&amp; m项,我们有两种情况:
使用此递归,您只需处理最简单的情况:连接两个列表,其中一个列表为空。 它会快速使用排列。 希望它有所帮助。
答案 4 :(得分:1)
长(ish)单线
from itertools import *
from copy import deepcopy
list({''.join(str(l.pop(0)) for l in deepcopy(p)) for p in permutations(chain(repeat(list_1, len(list_1)), repeat(list_2, len(list_2))))})
有关解释,请参阅我对类似问题All possible ways to interleave two strings的回答。