更新 我发现我对原始问题并不清楚。 给出一个列表
last_eqn=[[3], [2, 1]]
和列表字典:
{2: [[5], [3, 1]],
3: [[8], [5, 1]],
5: [[13], [8, 1]],
8: [[21], [13, 1]],
13: [[34], [21, 1]],
21: [[55], [34, 1]],
34: [[89], [55, 1]]}
替换last_eqn中的每个数字,如果key == number在last_eqn中,则使用键的值。 对于Eg:
[[3], [2, 1]] = [[[[8], [5, 1]]], [2, 1]] =
[[[[8], [[[13], [8, 1]], 1]]], [2, 1]] =
[[[[[[21], [13, 1]]], [[[13], [[[21], [13, 1]], 1]], 1]]], [2, 1]]
我有一个初步清单:
last_eqn=[[3], [2, 1]]
和字典框架
{2: [[5], [3, 1]],
3: [[8], [5, 1]],
5: [[13], [8, 1]],
8: [[21], [13, 1]],
13: [[34], [21, 1]],
21: [[55], [34, 1]],
34: [[89], [55, 1]]}
我想用last_eqn中的数字值替换,直到所有数字都归结为最后一个(这里它们将是89和55) 这是每个列表的结构。
我写了这个:
def recur_subs(last_eqn,frame=frame):
"""
{2: [[5], [3, 1]],
3: [[8], [5, 1]],
5: [[13], [8, 1]],
8: [[21], [13, 1]],
13: [[34], [21, 1]],
21: [[55], [34, 1]],
34: [[89], [55, 1]]}
"""
for key in frame:
fst,scnd = last_eqn
fst_num,scnd_num=fst[0],scnd[0]
#fst_marker,scnd_marker = 0,0
while not isinstance(fst_num,int):
#fst_marker += 1
fst_num = fst_num[0]
while not isinstance(scnd_num,int):
#scnd_marker += 1
scnd_num = scnd_num[0]
print fst_num,scnd_num
if isinstance(fst_num,int) and fst_num in frame:
fst[0] = (frame[fst_num])
if isinstance(scnd_num,int) and scnd_num in frame:
scnd[0] = (frame[scnd_num])
last_eqn = [fst,scnd]
print last_eqn
它没有正确解决。我试图纠正它,但这是输出:
recur_subs(last_eqn,frame)
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
55 89
[[[[55], [34, 1]]], [[[89], [55, 1]], 1]]
这很慢,但我想找到解决问题的正确方法。 应该搜索这些值并适当地替换为[[89],[55,1]]
答案 0 :(得分:1)
我不完全理解你的算法,但我做了一个猜测,这可能是错的。这样的事情怎么样?
def my_substitution(last_equation, frame=frame):
while True:
key = last_equation[1][0]
print last_equation
if key in frame:
last_equation = frame[key]
else:
break
print last_equation
输出:
[[3], [2, 1]]
[[5], [3, 1]]
[[8], [5, 1]]
[[13], [8, 1]]
[[21], [13, 1]]
[[34], [21, 1]]
[[55], [34, 1]]
[[89], [55, 1]]
[[89], [55, 1]]
让我确保我正确理解您的算法。
substitute_once()
。对于substitute_once()
,让我们尝试最简单的输入:
>>> substitute_once(2)
[[5], [3, 1]]
如果输入是一个列表,那么substitute_once()
将为每个元素递归调用自身:
>>> substitute_once([[3], [2, 1]])
[[[[8], [5, 1]]], [[[5], [3, 1]], 1]]
这是因为我们将3
替换为[[8], [5, 1]]
,将2
替换为[[5], [3, 1]]
假设我们知道如何更换它一次,我们可以反复进行,直到我们再也无法更换。换句话说,substitute_once(the_list) == the_list
。
如果我的假设是正确的,那么我就是这样做的:
def substitute_once(n, frame=frame):
if isinstance(n, list):
return [substitute_once(x) for x in n]
if n in frame:
return frame[n]
else:
return n
def substitute_recursively(last_equation,frame=frame):
while True:
new_equation = substitute_once(last_equation)
print new_equation
if new_equation == last_equation:
break
last_equation = new_equation
substitutte_once()
是直截了当的,正如我在上面的第1-3点中所讨论的那样。substitute_recursively()
同样简单,因为我们只解决了一个小问题:只需重复调用substitute_once()
,直到新列表和旧列表相同,这意味着我们无法再进行任何替换。最终输出很长,我没有看到任何显示它的点。如果这是你想要的,请告诉我。
答案 1 :(得分:1)
由于您希望以递归方式替换这些项目,因此您必须在某些时候调用替换函数本身。在recurs_subs
函数中,我将last_eqn
中的每个第一个列表替换为字典中相应的列表列表,我也将其替换为recurs_subs
第一
import copy
def recur_subs(last_eqn, frame):
for item in last_eqn:
if type(item[0]) == int and item[0] in frame:
substitute = copy.deepcopy(frame[item[0]])
item[0] = recur_subs(substitute, frame)
return last_eqn
输出:
[[[[[[[[55], [[[89], [55, 1]], 1]]], [[[[[89], [55, 1]]], [[[55],[[[89],
[55, 1]], 1]], 1]], 1]]], [[[[[[[89], [55, 1]]], [[[55], [[[89], [55, 1]], 1]],
1]]], [[[[[55], [[[89], [55, 1]], 1]]], [[[[[89], [55, 1]]], [[[55], [[[89],
[55, 1]], 1]], 1]], 1]], 1]], 1]]], [[[[[[[[[89], [55, 1]]], [[[55], [[[89],
[55, 1]], 1]], 1]]], [[[[[55], [[[89], [55, 1]], 1]]], [[[[[89], [55, 1]]],
[[[55], [[[89], [55, 1]], 1]], 1]], 1]], 1]]], [[[[[[[55], [[[89], [55, 1]],
1]]], [[[[[89], [55, 1]]], [[[55], [[[89], [55, 1]], 1]], 1]], 1]]],
[[[[[[[89], [55, 1]]], [[[55], [[[89], [55, 1]], 1]], 1]]], [[[[[55],
[[[89], [55, 1]], 1]]], [[[[[89], [55, 1]]], [[[55], [[[89], [55, 1]], 1]],
1]], 1]], 1]], 1]], 1]], 1]]
如您所见,我还决定复制列表列表以防止修改列表字典中存储的对象。
但也许您希望修改这些对象,因为无论如何替换都是相同的。它可能会使替换更快,因为2
的替换将存储在内存中,而不是在遇到的每2
时计算,依此类推每个替换数字。
如果是这种情况,只需删除深层副本,然后直接将frame[item[0]]
传递给recurs_subs
。
答案 2 :(得分:1)
递归替换列表中的每个元素(列表列表列表...)
def recsub( last_eqn ):
if type(last_eqn) != list:
if last_eqn in repdic:
last_eqn = repdic[last_eqn]
else:
for i in range(len(last_eqn)):
last_eqn[i] = recsub( last_eqn[i] )
return last_eqn
并检查新列表是否与旧列表相同。您需要进行deepcopy
操作。
last_eqn=[[3], [2, 1]]
A = last_eqn
B = 0
import copy
while 1:
recsub(A)
if A==B:
break
else:
B=copy.deepcopy(A)
答案 3 :(得分:1)
<强>更新强>
我同意Hai Vu的,Fury的,ysakamoto的答案。 有了Hai,功能显然已经很好地分解了。 虽然Fury's在本质上更具天生性和简洁性。 我修改了我的recur_subs代码,并在此处对所有答案进行了比较:
last_eqn=[[3], [2, 1]]
%timeit recsub(last_eqn) #ysakomoto's
10000 loops, best of 3: 174 µs per loop
%timeit recur_subs(last_eqn,frame) #mine
10000 loops, best of 3: 168 µs per loop
%timeit recur_subs2(last_eqn,frame) #Fury's
1000000 loops, best of 3: 578 ns per loop
即。 0.578微秒/环
%timeit substitute_recursively(last_eqn,frame) #Hai Vu's
1000 loops, best of 3: 361 µs per loop
%timeit substitute_recursively(last_eqn,frame) #Hai Vu's No Print just return
10000 loops, best of 3: 145 µs per loop
这是我的代码:
def recur_subs(last_eqn,frame=frame):
"""
last_eqn=[[3], [2, 1]]
{2: [[5], [3, 1]],
3: [[8], [5, 1]],
5: [[13], [8, 1]],
8: [[21], [13, 1]],
13: [[34], [21, 1]],
21: [[55], [34, 1]],
34: [[89], [55, 1]]}
"""
for enum,lst_item in enumerate(last_eqn):
if isinstance(lst_item,int):
if lst_item in frame:
last_eqn[enum] = recur_subs(frame[lst_item])
elif isinstance(lst_item,list): lst_item = recur_subs(lst_item)
return last_eqn
如果我是正确的,Fury的代码执行得最快到最慢:Fury的&gt; Hai Vu的(没有印刷品)&gt;我的&gt; ysakomoto的