简体   繁体   English

搜索并用数字替换字典查找中的列表

[英]Search & Substitute numbers for list from a dictionary lookup

UPDATE I see I wasn't clear on the original question. 更新我看到我不清楚原来的问题。 Given a list 给出清单

last_eqn=[[3], [2, 1]]

and a list dictionary: 和列表字典:

{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]]}

Substitute for every number in last_eqn, with the value of the key if key==number in the last_eqn. 如果last_eqn中的key == number,则用key的值替换last_eqn中的每个数字。 For 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]]

I have an initial list: 我有一个初始清单:

last_eqn=[[3], [2, 1]]

and a dictionary 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]]}

I want to substitute the values of numbers in last_eqn till all the numbers boil down to the last (here they will be in terms of 89 and 55) That is the structure of each list. 我想替换last_eqn中的数字值,直到所有数字都沸腾到最后一个(这里分别是89和55)。这就是每个列表的结构。

I wrote this: 我这样写:

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

It doesn't solve properly. 它无法正确解决。 Im trying to correct it but here's the output: 我正在尝试纠正它,但这是输出:

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]]

This is slow but I want to get down to the correct way of solving it. 这很慢,但我想解决问题的正确方法。 The values should be searched and substituted properly going down till [[89], [55, 1]] 应当搜索这些值并适当地替换它们直到[[89],[55,1]]

I don't fully understand your algorithm, but I made a guess, which could be wrong. 我不完全了解您的算法,但我做出了猜测,这可能是错误的。 How about something like this? 这样的事情怎么样?

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

Output: 输出:

[[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]]

Update 更新资料

Let me make sure that I understand your algorithm correctly. 让我确保我正确理解您的算法。

  1. Let's start out trying to substitute just once. 让我们开始尝试只替换一次。 I named my function substitute_once() . 我将函数命名为substitute_once()
  2. For substitute_once() , let's try the simplest input: 对于substitute_once() ,让我们尝试最简单的输入:

     >>> substitute_once(2) [[5], [3, 1]] 
  3. If the input is a list, then substitute_once() will call itself recursively for each element: 如果输入是列表,那么substitute_once()将为每个元素递归调用自身:

     >>> substitute_once([[3], [2, 1]]) [[[[8], [5, 1]]], [[[5], [3, 1]], 1]] 

    This is because we replace both the 3 with [[8], [5, 1]] and 2 with [[5], [3, 1]] 这是因为我们将3替换为[[8], [5, 1]]2替换为[[5], [3, 1]]

  4. Assume that we know how to replace it once, we can do it repeatedly until we can no longer replace. 假设我们知道如何更换一次,那么我们可以重复进行直到不再更换为止。 In other word, substitute_once(the_list) == the_list . 换句话说, substitute_once(the_list) == the_list

If my assumptions are correct, then here is how I would do it: 如果我的假设是正确的,那么这就是我的做法:

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

Discussion 讨论区

  • substitutte_once() is straight-forward, as I have discussed it in bullet points 1-3 above. substitutte_once()很简单,正如我在上面的要点1-3中所讨论的那样。
  • substitute_recursively() is equally simple because we only solve a small problem: just call substitute_once() repeatedly until the new list and old are the same, meaning we can no longer make any substitution. substitute_recursively()同样很简单,因为我们只解决了一个小问题:重复调用substitute_once()直到新列表和旧列表相同为止,这意味着我们无法再进行任何替换。

The final output is so long, I don't see any point showing it. 最终输出太长了,我看不到任何一点。 Please let me know if this is what you want. 请让我知道这是否是您想要的。

Since you want to recursively substitute those items, you have to call, at some point, the substitution function in itself. 由于要递归替换这些项目,因此必须在某个时候调用自身的替换函数。 In the recurs_subs function, I replace every first number of the lists in last_eqn by the corresponding list of lists in the dictionary, in which I have substituted numbers too, by passing them to recurs_subs first. recurs_subs函数中,我将last_eqn列表的每个第一个数字替换为字典中相应的列表列表,其中我也替换了数字,方法是recurs_subs它们传递给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

Output: 输出:

[[[[[[[[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]]

As you can see, I also decided to copy the list of lists to prevent modifying objects stored in the list dictionary. 如您所见,我还决定复制列表列表,以防止修改存储在列表字典中的对象。

But maybe you want those objects to be modified, since the substitutions would be the same anyway. 但是也许您想要修改这些对象,因为无论如何替换都是一样的。 It would probably make the substitutions faster, since the substitution for a 2 would be stored in memory instead of computed at every 2 encountered, and so on for every substituted numbers. 或许,这将使得替代更快,因为一个替代2将被存储在内存中,而不是在每一个计算2的每一个取代号遇到,等等。

If this is the case, just remove the deep copy and directly pass frame[item[0]] to recurs_subs . 如果是这种情况,只需删除深层副本,然后将frame[item[0]]直接传递给recurs_subs

Recursively substitute each element in the list (of list of list of list...) 递归替换列表中的每个元素(列表的列表...)

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

And check if the new list is same as the old list. 并检查新列表是否与旧列表相同。 You need a deepcopy operation for this. 为此,您需要进行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)

UPDATE 更新

I agree with Hai Vu's,Fury's,ysakamoto's answers. 我同意Hai Vu,Fury,ysakamoto的回答。 With Hai's, functions were clearly broken down very well. 对于Hai来说,功能显然被很好地分解了。 Fury's was more inherently in nature and concise though. 愤怒的本质上更简洁。 I modified my recur_subs code and I did a compare with all answers here: 我修改了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

ie 0.578 micro-sec /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

And here's my code: 这是我的代码:

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

If I'm correct Fury's code executes fastest to slowest: Fury's > Hai Vu's(no print) > mine > ysakomoto's 如果我正确,那么Fury的代码执行速度最快到最慢:Fury的> Hai Vu(无打印)>我的> ysakomoto的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM