Question

when I try to create a dictionary from a list of list, python only saves the info from the last list within the list when I use comprehensions.

prediction_dict = dict()
for user_prediction in sliding:
    for cur_loc, prediction_list in user_prediction:
        prediction_dict[(cur_loc.user, cur_loc.time)] = prediction_list
        print prediction_dict

how can I achieve this in a more pythonic way, with list comprehension?

i try this:

prediction_dict = {(cur_loc.user, cur_loc.time): prediction_list for cur_loc, prediction_list in user_prediction for user_prediction in sliding}

but it only saves data of the last list within the lists?

why?

Was it helpful?

Solution

As the others have mentioned, your comprehension is not working because the for statements need to be switched. However, there is a simple reason as to why your code was doing what it was doing. If you do this:

del(user_prediction) #Ensure we aren't using a previously defined version
prediction_dict = {(cur_loc.user, cur_loc.time): prediction_list for cur_loc, prediction_list in user_prediction for user_prediction in sliding}

Then you will get an error like this:

NameError: name 'user_prediction' is not defined

So I'm guessing when you where trying it, you were doing something like this:

prediction_dict = dict()
for user_prediction in sliding:
    for cur_loc, prediction_list in user_prediction:
        prediction_dict[(cur_loc.user, cur_loc.time)] = prediction_list
        print prediction_dict

prediction_dict = {(cur_loc.user, cur_loc.time): prediction_list for cur_loc, prediction_list in user_prediction for user_prediction in sliding}
print prediction_dict

If you print the value of user_prediction after the for loops and before the comprehension, you will find it refers to the last entry in sliding. This wouldn't be a problem, except from the NameError we see that the comprehension as you have it is trying to use an old value rather than the new value you want to give it. What's going on behind the scenes is something like this:

prediction_dict = {}
loop_one_input = user_prediction
for cur_loc, prediction_list in loop_one_input:
    loop_two_input = sliding
    for user_prediction in loop_two_input:
        prediction_dict[(cur_loc.user, cur_loc.time)] = prediction_list

So as you can see, by the time user_prediction is reassigned to a new value (in the inner for loop) the outer for loop is already using the old value. This isn't exactly what's happening, but hopefully it gives you a good enough idea to understand why your dictionary comprehension was not working correctly.

OTHER TIPS

When converting a nested for loop to a nested list comprehension the outer loops need to come first, so it looks like you just need to switch the order of the iteration within your comprehension (broken up onto multiple lines for clarity:

prediction_dict = {(cur_loc.user, cur_loc.time): prediction_list
                   for user_prediction in sliding
                   for cur_loc, prediction_list in user_prediction}

You've almost got it, change the order of for statements in the comprehension:

prediction_dict = {(cur_loc.user, cur_loc.time): prediction_list 
                   for user_prediction in sliding 
                   for cur_loc, prediction_list in user_prediction}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top