Reputation: 1025
I have the following Python dictionaries:
road_dict = {0:[1L,2L], 1:[3L], 2:[4L,5L]}
dist_dict = {1L: 4.1, 2L: 2.1, 3L: 4, 4L: 2.1, 5L: 6}
num_dict = {0:[2,4], 1:[5], 2:[1,3]
The first one, road_dict, has road IDs as keys and home IDs associated as values. The second, dist_dict, has the same home IDs as keys and their distance along the road as values. The third, num_dict, has the same road IDs as keys and number associated with the same homes as values.
I am trying to re-number these homes based on their distance along the road. A simple version of what I'm looking to get is this:
new_dict = {0:[4,2], 1:[5], 2:[1,3]}
For key 0, the order of numbers has switched because home ID 1L is farther along the road than 2L. This also means that 4 now pertains to 1L and 2 pertains to 2L.
I have some other issues, however, due to the way my dictionaries are separated. I'm looking for an approach that will the information together in one dictionary, so I can more easily keep track of which home number belongs to which home ID.
Ultimately, what I'm looking to achieve is this-- 1 is the index of a field I'm trying to update (with the new, sorted number):
final_dict = {1L:{1:4}, 2L:{1:2}, 3L:{1:5}, 4L:{1:1}, 5L:{1:3}}
A missing piece I just realized could be useful This creates a dictionary with a simple incrementation of the order of each home along the line. I think this belongs with my original question. :
another_dict = {0:[2,1], 1:[1], 2:[1,2]}
UPDATE I tried the following code using the following dictionaries, but things are still not sorting correctly. While the homes are sorted by distance and ready to be numbered sequentially, I am also looking to keep the set of existing numbers and switching them around to be in the right order based on distance. This code allows each home to keep their existing number regardless of distance order.
i_road_dict = {421: [32L, 33L, 34L], 422: [9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 27L, 28L, 29L, 35L, 36L, 37L, 38L, 39L], 423: [66L, 67L, 72L, 73L, 76L], 623: [2L], 624: [0L], 627: [3L, 4L], 629: [86L], 317: [50L, 63L, 64L, 65L, 70L, 71L, 74L, 75L, 81L, 82L, 83L, 85L, 87L, 88L]}
i_num_dict = {421: [15, 19, 21], 422: [31, 33, 35, 39, 43, 31, 29, 25, 23, 19, 15, 41, 49, 47, 9, 7, 11, 13, 17], 423: [11, 13, 17, 23, 27], 623: [1], 624: [13], 627: [9, 5], 629: [7], 317: [109, 151, 45, 47, 143, 141, 133, 131, 101, 95, 91, 81, 57, 63]}
i_distance_dict = {0L: 61.488059367717, 2L: 8.021516228782936, 3L: 45.52003866488311, 4L: 25.20730241437668, 9L: 157.844303290623, 10L: 162.61477713824982, 11L: 177.70675687888885, 12L: 194.7672626115625, 13L: 205.85748324109224, 14L: 151.29798366856477, 15L: 147.66380499017282, 16L: 119.9462825595851, 17L: 114.98507682692828, 18L: 98.45714293590342, 19L: 87.46475300724273, 27L: 209.53486929892026, 28L: 232.3460547737345, 29L: 239.89698687340757, 32L: 71.13973224724995, 33L: 90.16514887960331, 34L: 106.48078486409304, 35L: 30.04092989941455, 36L: 39.961250890703326, 37L: 53.44419657185303, 38L: 83.59339524297145, 39L: 85.66697660333085, 50L: 549.0312971771257, 63L: 753.3816549180551, 64L: 225.80699058127138, 65L: 237.74936014259308, 66L: 58.12282403458027, 67L: 63.3770825337218, 70L: 708.6717387628081, 71L: 704.5817839747034, 72L: 87.27533124959758, 73L: 113.56828281454557, 74L: 658.1701619456403, 75L: 654.8787862943727, 76L: 137.46561448886376, 81L: 501.846856735727, 82L: 478.70973384256945, 83L: 456.2651041053348, 85L: 407.21753873616143, 86L: 34.367967658321774, 87L: 286.4419958357572, 88L: 317.3584642656698}
After using this code:
i_homes = []
for road_id, home_ids in i_road_dict.items():
i_home_numbers_on_road = i_num_dict[road_id]
for home_id, home_number in zip(home_ids, i_home_numbers_on_road):
home = {}
home['home_id'] = home_id
home['home_number'] = home_number
home['road_id'] = road_id
home['distance'] = distance_dict[home_id]
i_homes.append(home)
i_sorted_dict = {}
for road_id in i_road_dict:
i_homes_on_road = [home for home in i_homes if home['road_id'] == road_id]
i_ordered_homes = sorted(i_homes_on_road, key=lambda h: h['distance'])
i_sorted_dict[road_id] = i_ordered_homes
I got this result:
i_sorted_dict = {421: [{'home_id': 32L, 'home_number': 15, 'road_id': 421, 'distance': 71.13973224724995}, {'home_id': 33L, 'home_number': 19, 'road_id': 421, 'distance': 90.16514887960331}, {'home_id': 34L, 'home_number': 21, 'road_id': 421, 'distance': 106.48078486409304}], 422: [{'home_id': 35L, 'home_number': 9, 'road_id': 422, 'distance': 30.04092989941455}, {'home_id': 36L, 'home_number': 7, 'road_id': 422, 'distance': 39.961250890703326}, {'home_id': 37L, 'home_number': 11, 'road_id': 422, 'distance': 53.44419657185303}, {'home_id': 38L, 'home_number': 13, 'road_id': 422, 'distance': 83.59339524297145}, {'home_id': 39L, 'home_number': 17, 'road_id': 422, 'distance': 85.66697660333085}, {'home_id': 19L, 'home_number': 15, 'road_id': 422, 'distance': 87.46475300724273}, {'home_id': 18L, 'home_number': 19, 'road_id': 422, 'distance': 98.45714293590342}, {'home_id': 17L, 'home_number': 23, 'road_id': 422, 'distance': 114.98507682692828}, {'home_id': 16L, 'home_number': 25, 'road_id': 422, 'distance': 119.9462825595851}, {'home_id': 15L, 'home_number': 29, 'road_id': 422, 'distance': 147.66380499017282}, {'home_id': 14L, 'home_number': 31, 'road_id': 422, 'distance': 151.29798366856477}, {'home_id': 9L, 'home_number': 31, 'road_id': 422, 'distance': 157.844303290623}, {'home_id': 10L, 'home_number': 33, 'road_id': 422, 'distance': 162.61477713824982}, {'home_id': 11L, 'home_number': 35, 'road_id': 422, 'distance': 177.70675687888885}, {'home_id': 12L, 'home_number': 39, 'road_id': 422, 'distance': 194.7672626115625}, {'home_id': 13L, 'home_number': 43, 'road_id': 422, 'distance': 205.85748324109224}, {'home_id': 27L, 'home_number': 41, 'road_id': 422, 'distance': 209.53486929892026}, {'home_id': 28L, 'home_number': 49, 'road_id': 422, 'distance': 232.3460547737345}, {'home_id': 29L, 'home_number': 47, 'road_id': 422, 'distance': 239.89698687340757}], 423: [{'home_id': 66L, 'home_number': 11, 'road_id': 423, 'distance': 58.12282403458027}, {'home_id': 67L, 'home_number': 13, 'road_id': 423, 'distance': 63.3770825337218}, {'home_id': 72L, 'home_number': 17, 'road_id': 423, 'distance': 87.27533124959758}, {'home_id': 73L, 'home_number': 23, 'road_id': 423, 'distance': 113.56828281454557}, {'home_id': 76L, 'home_number': 27, 'road_id': 423, 'distance': 137.46561448886376}], 623: [{'home_id': 2L, 'home_number': 1, 'road_id': 623, 'distance': 8.021516228782936}], 624: [{'home_id': 0L, 'home_number': 13, 'road_id': 624, 'distance': 61.488059367717}], 627: [{'home_id': 4L, 'home_number': 5, 'road_id': 627, 'distance': 25.20730241437668}, {'home_id': 3L, 'home_number': 9, 'road_id': 627, 'distance': 45.52003866488311}], 629: [{'home_id': 86L, 'home_number': 7, 'road_id': 629, 'distance': 34.367967658321774}], 317: [{'home_id': 64L, 'home_number': 45, 'road_id': 317, 'distance': 225.80699058127138}, {'home_id': 65L, 'home_number': 47, 'road_id': 317, 'distance': 237.74936014259308}, {'home_id': 87L, 'home_number': 57, 'road_id': 317, 'distance': 286.4419958357572}, {'home_id': 88L, 'home_number': 63, 'road_id': 317, 'distance': 317.3584642656698}, {'home_id': 85L, 'home_number': 81, 'road_id': 317, 'distance': 407.21753873616143}, {'home_id': 83L, 'home_number': 91, 'road_id': 317, 'distance': 456.2651041053348}, {'home_id': 82L, 'home_number': 95, 'road_id': 317, 'distance': 478.70973384256945}, {'home_id': 81L, 'home_number': 101, 'road_id': 317, 'distance': 501.846856735727}, {'home_id': 50L, 'home_number': 109, 'road_id': 317, 'distance': 549.0312971771257}, {'home_id': 75L, 'home_number': 131, 'road_id': 317, 'distance': 654.8787862943727}, {'home_id': 74L, 'home_number': 133, 'road_id': 317, 'distance': 658.1701619456403}, {'home_id': 71L, 'home_number': 141, 'road_id': 317, 'distance': 704.5817839747034}, {'home_id': 70L, 'home_number': 143, 'road_id': 317, 'distance': 708.6717387628081}, {'home_id': 63L, 'home_number': 151, 'road_id': 317, 'distance': 753.3816549180551}]}
At least for road 422, the homes are still out of order. I was expecting this (done by hand, so I hope I didn't miss anything) which switched the existing numbers around to sort them based on distance:
422: [{'home_id': 35L, 'home_number': 7, 'road_id': 422, 'distance': 30.04092989941455}, {'home_id': 36L, 'home_number': 9, 'road_id': 422, 'distance': 39.961250890703326}, {'home_id': 37L, 'home_number': 11, 'road_id': 422, 'distance': 53.44419657185303}, {'home_id': 38L, 'home_number': 13, 'road_id': 422, 'distance': 83.59339524297145}, {'home_id': 39L, 'home_number': 15, 'road_id': 422, 'distance': 85.66697660333085}, {'home_id': 19L, 'home_number': 17, 'road_id': 422, 'distance': 87.46475300724273}, {'home_id': 18L, 'home_number': 19, 'road_id': 422, 'distance': 98.45714293590342}, {'home_id': 17L, 'home_number': 23, 'road_id': 422, 'distance': 114.98507682692828}, {'home_id': 16L, 'home_number': 25, 'road_id': 422, 'distance': 119.9462825595851}, {'home_id': 15L, 'home_number': 29, 'road_id': 422, 'distance': 147.66380499017282}, {'home_id': 14L, 'home_number': 31, 'road_id': 422, 'distance': 151.29798366856477}, {'home_id': 9L, 'home_number': 31, 'road_id': 422, 'distance': 157.844303290623}, {'home_id': 10L, 'home_number': 33, 'road_id': 422, 'distance': 162.61477713824982}, {'home_id': 11L, 'home_number': 35, 'road_id': 422, 'distance': 177.70675687888885}, {'home_id': 12L, 'home_number': 39, 'road_id': 422, 'distance': 194.7672626115625}, {'home_id': 13L, 'home_number': 41, 'road_id': 422, 'distance': 205.85748324109224}, {'home_id': 27L, 'home_number': 43, 'road_id': 422, 'distance': 209.53486929892026}, {'home_id': 28L, 'home_number': 47, 'road_id': 422, 'distance': 232.3460547737345}, {'home_id': 29L, 'home_number': 49, 'road_id': 422, 'distance': 239.89698687340757}]
another update The issue was with the creation of final_dict as the answer provides. I adapted the sort to the new numbers and zipped with the the ordered homes instead of "homes_on_road":
i_final_dict = {}
for road_id in i_road_dict:
i_homes_on_road = [home for home in i_homes if home['road_id'] == road_id]
i_ordered_homes = sorted(i_homes_on_road, key=lambda h: h['distance'])
#i_ordered_nums = [home['home_number'] for home in i_ordered_homes]
i_ordered_nums = sorted([home['home_number'] for home in i_ordered_homes])
for home, new_number in zip(i_ordered_homes, i_ordered_nums):
i_final_dict[home['home_id']] = {sort_num_idx:new_number}
Upvotes: 1
Views: 304
Reputation: 29013
Does it have to be that terse? How about making a dictionary per home, with all the related information and putting those in a list:
from pprint import pprint
road_dict = {0:[1L,2L], 1:[3L], 2:[4L,5L]} # road_id:home_id
dist_dict = {1L: 4.1, 2L: 2.1, 3L: 4, 4L: 2.1, 5L: 6} # home_id:distance
num_dict = {0:[2,4], 1:[5], 2:[1,3]} # road_id:[house_numbers]
homes = []
for road_id, home_ids in road_dict.items():
home_numbers_on_road = num_dict[road_id]
for home_id, home_number in zip(home_ids, home_numbers_on_road):
home = {'home_id': home_id,
'home_number': home_number,
'road_id': road_id,
'distance': dist_dict[home_id]}
homes.append(home)
pprint(homes)
Gives a list, with a dictionary for each home, keeping all the things together:
[{'distance': 4.1, 'home_id': 1L, 'home_number': 2, 'road_id': 0},
{'distance': 2.1, 'home_id': 2L, 'home_number': 4, 'road_id': 0},
{'distance': 4, 'home_id': 3L, 'home_number': 5, 'road_id': 1},
{'distance': 2.1, 'home_id': 4L, 'home_number': 1, 'road_id': 2},
{'distance': 6, 'home_id': 5L, 'home_number': 3, 'road_id': 2}]
And then you get a much easier time of building things out of it:
new_dict = {}
for road_id in road_dict:
homes_on_road = [home for home in homes if home['road_id'] == road_id]
ordered_homes = sorted(homes_on_road, key=lambda h: h['distance'])
new_dict[road_id] = ordered_homes
pprint(new_dict)
Gives:
{0: [{'distance': 2.1, 'home_id': 2L, 'home_number': 4, 'road_id': 0},
{'distance': 4.1, 'home_id': 1L, 'home_number': 2, 'road_id': 0}],
1: [{'distance': 4, 'home_id': 3L, 'home_number': 5, 'road_id': 1}],
2: [{'distance': 2.1, 'home_id': 4L, 'home_number': 1, 'road_id': 2},
{'distance': 6, 'home_id': 5L, 'home_number': 3, 'road_id': 2}]}
Which is your 0:4,2, 1:5, 2:1,3
intermediate result.
Although this has reordered the homes and not renumbered them. But then what does it mean to renumber home 5 on street 2, when it's the only home on street 2? Assuming they go 1, 2... on each street:
new_dict = {}
for road_id in road_dict:
homes_on_road = [home for home in homes if home['road_id'] == road_id]
ordered_homes = sorted(homes_on_road, key=lambda h: h['distance'])
for position, home in enumerate(ordered_homes):
home['home_number'] = position + 1
new_dict[road_id] = ordered_homes
pprint(new_dict)
Which gives:
{0: [{'distance': 2.1, 'home_id': 2L, 'home_number': 1, 'road_id': 0},
{'distance': 4.1, 'home_id': 1L, 'home_number': 2, 'road_id': 0}],
1: [{'distance': 4, 'home_id': 3L, 'home_number': 1, 'road_id': 1}],
2: [{'distance': 2.1, 'home_id': 4L, 'home_number': 1, 'road_id': 2},
{'distance': 6, 'home_id': 5L, 'home_number': 2, 'road_id': 2}]}
Which has put the houses to show in the order they are physically in (by distance), and renumbered them sequentially from closest to furthest on a road-by-road basis.
[Edit: maybe correction]
Edit: Is this what the final_dict should be?
# order the homes by distance
# pair up the homes by position with the home_numbers by distance
final_dict = {}
for road_id in road_dict:
homes_on_road = [home for home in homes if home['road_id'] == road_id]
ordered_homes = sorted(homes_on_road, key=lambda h: h['distance'])
ordered_nums = [home['home_number'] for home in ordered_homes]
for home, new_number in zip(homes_on_road, ordered_nums):
final_dict[home['home_id']] = {1:new_number}
pprint(final_dict)
Giving:
{1L: {1: 4}, 2L: {1: 2}, 3L: {1: 5}, 4L: {1: 1}, 5L: {1: 3}}
Upvotes: 1
Reputation: 6693
Making new_dict
:
>>> new_dict = dict()
>>> for ikey in road_dict:
l = list(sorted(num_dict[ikey],key = lambda x:dist_dict[road_dict[ikey][num_dict[ikey].index(x)]]))
print l
>>> for ikey in road_dict:
l = list(sorted(num_dict[ikey],key = lambda x:dist_dict[road_dict[ikey][num_dict[ikey].index(x)]]))
new_dict[ikey] = l
>>> new_dict
{0: [4, 2], 1: [5], 2: [1, 3]}
Making final_dict
:
>>> x = 'x'
>>> for ikey in road_dict:
for j in range(len(road_dict[ikey])):
final_dict[road_dict[ikey][j]] = {x : new_dict[ikey][j]}
>>> final_dict
{1L: {'x': 4}, 2L: {'x': 2}, 3L: {'x': 5}, 4L: {'x': 1}, 5L: {'x': 3}}
I hope this works for you!
Upvotes: 1