Reputation: 179
I have two lists which have been created by .csv files. The first consists of a branch id number and a list of corresponding flows. The second is the order in which I wish to have the branche ids and their corrsponding flows sorted. They are as follows:
branch_flows = [['1234-2321-1', [55, 76, 3, 55, 6]],
['1546-2645-1', [4, 6, 56, 3, 4]],
// ...
['4123-1234-1', [6, 12, -4, 7, 9]]
]
and
ordered_branches = ['1234-2321-1',
'1234-4123-1',
// ...
'1546-2645-1']
I am wondering how to sort branch_flows
the same way ordered_branches
is ordered, but for the flows to stay related to the same ids after sorting? The main difficulty being that some of the branch ids in branch_flows
first two parts are reversed, but I need them to be sorted as if they were not.
e.g. looking to the lists above, desired output would be having branch_flows
sorted in a way that the final list in branch_flows
was placed second in the sorted list (as 1234-4123-1
in ordered_branches
can equal both 1234-4123-1
AND 4123-1234-1
in branch_list
, as the order in branch_flows
can sometimes be the reverse of that in ordered_branches
).
I originally tried to use dictionarys as look up tables but ran into trouble with the reading reverse order part. Help much appreciated!
Upvotes: 2
Views: 670
Reputation: 21288
On the surface of things, it looks as if you could do this with one dict-build and two list traversals (you already have the sorted order, after all).
Something like:
flow_dict = {}
for flow in branch_flow:
# Sometimes, there's a reversal of the two parts of the key.
key_parts = flow[0].split('-')
flow_dict['-'.join(key_parts)] = flow
flow_dict['-'.join([key_parts[1], key_parts[0], key_parts[2])] = flow
branch_flows = [flow_dict[key] for key in ordered_branches]
Building the dict should be O(n) (N inserts, each at amortized O(1)), traversing the ordered list should be O(n) and fetching the values from the dict should be O(1)). This is likely better than anything you could do by sorting.
Upvotes: 2
Reputation: 157484
You need to construct an appropriate key
function to the Python sort
function.
Ignoring the reversed-order issue, it's quite easy:
def key(branch):
id, flows = branch
return ordered_branches.index(id)
Considering the reversed-order issue, we can use:
def key(branch):
id, flows = branch
try:
return ordered_branches.index(id)
except ValueError:
parts = id.split('-')
id = '-'.join((parts[1], parts[0], parts[2]))
return ordered_branches.index(id)
Now you can sort branch_flows
as sorted(branch_flows, key=key)
.
You can speed this up by turning ordered_branches
into a dictionary:
order_dict = dict((x, i) for i, x in enumerate(ordered_branches))
and instead of ordered_branches.index(id)
use order_dict[id]
(also change ValueError
to KeyError
).
As a time-space tradeoff you could construct the reversed-order ids in the dict:
def reverse_id(id):
parts = id.split('-')
return '-'.join((parts[1], parts[0], parts[2]))
order_dict = dict((x, i) for i, x in enumerate(ordered_branches))
order_dict.update((reverse_id(x), i) for x, i in order_dict.items())
Now your key function just looks like:
def key(branch):
id, flows = branch
return order_dict[id]
Upvotes: 3