TheRealFakeNews
TheRealFakeNews

Reputation: 8173

How to translate pythonic double for loop to standard code?

I have this chunk of pythonic code that I've been having trouble understanding:

paths = [[end]]
while paths and paths[0][0] != start:
    paths = [[parent] + path for path in paths for parent in childToParents[path[0]]]

where childToParents is:

defaultdict(<class 'set'>, {'cog': {'log', 'dog'},
                            'dog': {'dot'},
                            'dot': {'hot'},
                            'hit': None,
                            'hot': {'hit'},
                            'log': {'lot'},
                            'lot': {'hot'}})

end is "cog", start is "hit". The expected output of paths is:

[["hit","hot","lot","log","cog"],["hit","hot","dot","dog","cog"]]

I have tried multiple variations of a double for loop. One such attempt is:

    paths=[[end]]
    while paths and paths[0][0] != start:
        for i in xrange(len(paths)):
            for parent in childToParents[paths[i][0]]:
                paths[i] = [parent] + paths[i]

But this only gives me:

[["hit","hot","dot","dog","log","cog"]]

How can I translate the code to a standard double for loop?

Upvotes: 1

Views: 73

Answers (1)

mfitzp
mfitzp

Reputation: 15545

The nested for loop in the comprehension works left to right, so the rightmost loop is the inner loop, the left loop is the outer. For example —

a = [1,2,3]
b = [8,9,0]

[(a1, b1) for a1 in a for b1 in b]

Is equivalent to:

l = []
for a1 in a:
    for b1 in b:
      l.append((a1, b1))
l

Both will output the following if run

[(1, 8), (1, 9), (1, 0), (2, 8), (2, 9), (2, 0), (3, 8), (3, 9), (3, 0)]

For your example code —

paths = [[end]]
while paths and paths[0][0] != start:
    paths = [[parent] + path for path in paths for parent in childToParents[path[0]]]

Would be equivalent to:

paths = [[end]]
while paths and paths[0][0] != start:
    paths_, paths = paths, []
    for path in paths_:
        for parent in childToParents[path[0]]:
            paths.append([parent] + path)
paths

Note the paths_, paths = paths, [] needed to preserve the contents of paths to iterate over while still resetting it for the subsequent loop. Running the above with your inputs gives me:

[['hit', 'hot', 'dot', 'dog', 'cog'], ['hit', 'hot', 'lot', 'log', 'cog']]

Upvotes: 1

Related Questions