Python 2.7.9
您好我遇到了python如何处理我的排列算法的一些问题。
所以我希望我的函数采用 set_list = [1,2,3,4] 并返回该列表的所有排列。
这是我的想法。从左向右移动,从 set_list 的索引值0,1开始,使用 set_list [index +]的值翻转 set_list [index] 的值1] ,了解当你到达终点时,用 set_list [-1] 翻转 set_list [0] 。我以为这是gucci。
解 前进
1234
2134
2314
2341
1342
3142
3412
3421
1423
4123
4213
4231
然后,想法只是反向排序先前的子列表以获得所有可能的排列。
解决方案反向 4321 4312 4132 1432 2431 2413 2143 1243 3241 3214 3124 1324
我的python笔记
x = [1,2,3,4]
print(x)
j k k j
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)
x[0],x[1] = x[1],x[0]
print(x)
x[1],x[2] = x[2],x[1]
print(x)
x[2],x[3] = x[3],x[2]
print(x)
x[3],x[0] = x[0],x[3]
print(x)
代码返回:
[1, 2, 3, 4]
[2, 1, 3, 4]
[2, 3, 1, 4]
[2, 3, 4, 1]
[1, 3, 4, 2]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[1, 4, 2, 3]
[4, 1, 2, 3]
[4, 2, 1, 3]
[4, 2, 3, 1]
[1, 2, 3, 4]
因此有很多原因递归使用此函数不起作用(我不明白为什么):
def set_return(__LIST__,j,k):
__LIST__[j],__LIST__[k]=__LIST__[k],__LIST__[j]
return(__LIST__)
所以我决定尝试sudo-bullshit-hack一个解决方案,并且只是成功地成功地拔掉了我的头发。
第1步) 根据列表 x 的特征创建包含j,k垂直列表值的列表应该不是那么难吗?
x = [1,2,3,4]
set_0 = range(0,len(x))*(len(x)-1)
set_1 = set_0[1:len(set_0)]+[set_0[0]]
代码返回:
>>> set_0
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
>>> set_1
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
>>>
步骤2)
def shift(__LIST__,a,b):
j = int(__LIST__[a])
k = int(__LIST__[b])
__LIST__[a] = k
__LIST__[b] = j
return(__LIST__)
代码输出:
>>>
[1, 2, 3, 4]
[2, 1, 3, 4]
[2, 3, 1, 4]
[2, 3, 4, 1]
[1, 3, 4, 2]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[1, 4, 2, 3]
[4, 1, 2, 3]
[4, 2, 1, 3]
[4, 2, 3, 1]
[1, 2, 3, 4]
>>> set_0
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]
>>> set_1
[1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0]
>>> shift([1, 2, 3, 4],0,1)
[2, 1, 3, 4]
>>> shift([2, 1, 3, 4],1,2)
[2, 3, 1, 4]
>>> shift([2, 3, 1, 4],2,3)
[2, 3, 4, 1]
>>> shift([2, 3, 4, 1],3,0)
[1, 3, 4, 2]
>>>
然后我用这个:
chi = [1,2,3,4]
set_0 = range(0,len(chi))*(len(chi)-1)
set_1 = set_0[1:len(set_0)]+[set_0[0]]
to_return=[]
x = [1,2,3,4]
for i in range(len(set_0)):
insert=shift(x,set_0[i],set_1[i])
to_return.append(insert)
x = insert
得到:
[[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],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4],
[1, 2, 3, 4]]
有更简单的方法......是的。我可以“保护” x 或插入,或者甚至可能使用 list() ... face palm。无论如何发布。请享用。
答案 0 :(得分:1)
您在代码末尾遇到的问题是,您的所有insert
值都是对同一列表x
的引用,shift
函数会对其进行修改。您只会在[1, 2, 3, 4]
列表中看到to_return
值,因为这是x
的最终值。如果您在循环播放时打印x
,则会看到其他排列,但在to_return
中存储引用时,如果稍后修改x
,则不会保留该值。
与此比较:
x = [1, 2]
y = [x, x, x, x] # y contains several references to the list x
print(y) # prints [[1, 2], [1, 2], [1, 2], [1, 2]]
x[0] = 0 # modify x in place
print(y) # prints [[0, 2], [0, 2], [0, 2], [0, 2]], all the 1's are gone!
要解决此问题,您可以先复制列表,然后再将其附加到to_return
。稍后再次修改x
时,副本不会更改。 (另一种解决方案是更改shift
以返回新列表而不更改旧列表,但我将继续探索该选项。)当您存储副本时,您甚至不会需要关注shift
的返回值,您可以直接使用x
:
for i in range(len(set_0)):
shift(x,set_0[i],set_1[i]) # ignore the return value, which is another reference to x
to_return.append(x[:]) # append a copy of x
切片x[:]
是一种复制列表的简洁方法。如果你想要更明确一些(以一些额外的字符为代价),你可以使用list(x)
。这两个版本都很容易被经验丰富的Python程序员理解为副本。
在我完成这个答案之前,我想提出一些与您所询问的问题有些无关的其他建议。
首先,您的算法实际上并未找到您提供的列表的所有排列。例如,[4, 3, 2, 1]
永远不会出现(也不会出现4
之前3
直接出现的任何排列。因此,即使我上面提出的代码在做你想做的事情上“有效”,也可能在更大的意义上没有做正确的事情。
其次是风格问题。 Python允许您根据自己的喜好命名变量,但使用某些名称是一个非常糟糕的主意。在你的几个函数中,你使用名称__LIST__
,这是一个非常糟糕的参数名称。首先,为解释器保留双下划线名称。在将来的某个版本中,Python可能会在名称__LIST__
中存储一些特殊值(覆盖您正在使用它的任何内容)。或者它可能期望该名称保存某种特定类型的值,并且如果您在其中存储其他内容,则以某种方式中断。所以不要对任意变量使用双下划线!
即使我们忽略了双重下划线,__LIST__
也不是一个好名字,因为它很长很难打字。虽然更明确的名称通常是好的(例如number_of_things
可能比n
更好),但您必须平衡这一点,并且易于阅读和输入。使用list
可能不明智,因为这是内置类型的名称,但lst
是它的一个非常常见的缩写。
说到名字,最重要的是要保持一致。如果您将a
和b
用于一次性变量并不重要,但是当您有时使用这些变量时会更加混乱,有时则会使用j
和{{1} (他们的意思没有任何明显的区别)。
答案 1 :(得分:0)
def factorial(n):
c=1
for i in range(1,n+1):
c*=i
return(c)
def set_start(LIST):
to_return=[]
for i in range(len(LIST)):
insert=[]
for x in range(len(LIST)):
if LIST[i]!=LIST[x]:
insert.append(LIST[x])
to_return.append(insert)
return(to_return)
def set_builder(NESTED_LIST):
to_return=[]
for i in range(len(NESTED_LIST)):
to_return.append(set_start(NESTED_LIST[i]))
return(to_return)
def set_chain(NESTED_LIST):
to_return=[]
for i in range(len(NESTED_LIST)):
to_return+=NESTED_LIST[i]
return(to_return)
def set_expand(SET):
to_return=[]
for i in range(len(SET)):
to_return+=[SET[i]]*factorial(len(SET)-1)
return(to_return)
def set_rotation(SET):
set_0 = range(0,len(SET)-1,2)
set_1 = range(1,len(SET),2)
to_return=[]
for i in range(len(set_0)):
to_return+=[SET[set_1[i]],SET[set_0[i]]]
return(to_return)
def recursive_chain(SET):
sub_set_lengths=[]
for i in range(len(SET)):
sub_set_lengths.append(len(SET[i]))
sub_set_lengths = sorted(list(set(sub_set_lengths)),reverse=True)
to_return=[]
for i in range(len(sub_set_lengths)):
insert=[]
for x in range(len(SET)):
if sub_set_lengths[i]==len(SET[x]):
insert+=SET[x]
to_return.append(insert)
return(to_return)
def recursive_return(to_return):
to_return = [to_return]
initialize = set_start(to_return[-1])
while len(to_return[-1])!=2:
to_return+=initialize
to_chain = list(set_builder(list(initialize)))
to_pass = list(set_chain(list(to_chain)))
initialize = list(to_pass)
for i in range(len(to_return)):
if len(to_return[i])!=2:
to_return[i]=set_expand(to_return[i])
to_return = recursive_chain(to_return)
to_return+=[set_rotation(to_return[-1])]
return(to_return)
def PERMUTATIONS(SET):
to_return=[]
to_pop = recursive_return(SET)
while to_pop[-1]!=[]:
insert=[]
for i in range(len(SET)):
insert.append(to_pop[i][0])
to_return.append(insert)
for i in range(len(SET)):
to_pop[i].pop(0)
return(to_return)