Logic Behind Problem: When building a route you need two steps in order to perform a direction. For example if you go from Step1 to Step2 that is right. But Step1 to Step3 is left. The steps need to be in pairs in order to determine direction.
Issue:
I have a function that produces a 'Direction'
based on a pair of elements in 'StepName'
. If a routes 'StepName'
pair is already defined with 'Direction'
it should be able to produce the same 'Direction'
in another route dictionary if it contains the same pair of elements in a sequence of pairs. Doesn't matter at what index the pair is located in the list
For example:
104-1 to 104-2
produces'Left'
in'Direction'
104-2 to 105-A
produces'Right'
in'Direction'
105-A to 105-D
produces'Right'
in'Direction'
Code:
route1 = {
'RouteID': 1,
'StepID': [1, 2, 3, 4],
'StepName': ['104-1', '104-2', '105-A', '105-D'],
'Direction': ['Left', 'Right', 'Right']}
route2 = {
'RouteID': 2,
'StepID': [1, 2, 3, 4],
'StepName': ['104-2', '105-A', '105-C', '105-B'],
'Direction': []}
def routeMapper(longRoute, subRoute):
for i, v in enumerate(subRoute['StepName']):
found = False
for j, b in enumerate(longRoute['StepName']):
if v == b:
found = True
subRoute['Direction'].append(longRoute['Direction'][j])
if not found:
subRoute['Direction'].append(False)
routeMapper(route1, route2)
print(route2)
Output:
{'RouteID': 2, 'StepID': [1, 2, 3, 4], 'StepName': ['104-2', '105-A', '105-C', '105-B'], 'Direction': ['Right', 'Right', False, False]}
As you can see it is comparing what each index element direction it is assigned to. I want it to be seen in pairs instead of single.
Desired Output: (for 'Direction')
{'RouteID': 2, 'StepID': [1, 2, 3, 4], 'StepName': ['104-2', '105-A', '105-C', '105-B'], 'Direction': ['Right', False, False, False]}
The reason this output makes sense is because in route1
104-2 to 105-A
produces 'Right'
even though it is 1
and 2
in the index as a pair compared to it being at the 0
and 1
index in route2
. As long as the pair is found in the list it should be able to produce the direction.
CodePudding user response:
I first created a list named pair1
that will keep hold of i
& i 1
elements from the subRoute
's StepName
in the first loop. I've also done the same to the longRoute
in the second loop. Then if the first element of each pair and both of the pairs match, the function will append the direction
of that pair's. If not, it will append False
. (I had to restructure the loops to make this work)
def routeMapper(longRoute, subRoute):
for i in range(len(subRoute['StepName']) - 1):
found = False
pair1 = [subRoute['StepName'][i], subRoute['StepName'][i 1]]
for j in range(len(longRoute['StepName']) - 1):
pair2 = [longRoute['StepName'][j], longRoute['StepName'][j 1]]
if pair1[0]==pair2[0] and pair1 == pair2:
found = True
subRoute['Direction'].append(longRoute['Direction'][j])
if not found:
subRoute['Direction'].append(False)
#Output: {'RouteID': 2, 'StepID': [1, 2, 3, 4], 'StepName': ['104-2', '105-A', '105-C', '105-B'], 'Direction': ['Right', False, False]}
CodePudding user response:
I think the best solution would be to:
- create a dictionary mapping location pairs (
104-1
to104-2
) to their respective directions (Left
): functionroute_directions
- then, using this dictionnary we could compute the second route directions quite easily: function
derive_directions
def route_directions(route):
directions = route['Direction']
steps = route_steps(route)
return {step:direction for step, direction in zip(steps, directions)}
# Utility function (we could also use itertools.pairwise instead of this)
def route_steps(route):
return zip(route['StepName'], route['StepName'][1:])
def derive_directions(route, existing_directions):
return [existing_directions.get(step, False) for step in route_steps(route)]
Using all these functions, we can simply derive route2
directions from route1
:
route_directions = route_dict(route1)
route2['Direction'] = derive_directions(route2, route_directions)
Few things used here
- zip() that I also tried to describe a bit here. Basically it match two (or more) list element-wise, for example,
zip([1, 2, 3], [10, 20, 30])
, will produce the following tuples(1, 10), (2, 20), (3, 30)
. - This code also uses the fact that tuples can be used as dictionary keys, here is what the
route_directions
looks like:
{('104-1', '104-2'): 'Left',
('104-2', '105-A'): 'Right',
('105-A', '105-D'): 'Right'}