Reputation: 1191
I'm curious if there is a way to optimize in a situation I'm facing currently.
I have a list of strings representing categories to group and order data by:
['first', 'third', 'second']
This corresponds to a list of dicts containing objects of those categories which need to be sorted according to them:
[{'color':'yellow', 'section':'third'},{'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
The data list should be sorted via the order given in the first set, in this case resulting in:
[{'color':'red', 'section':'first'},{'color':'yellow', 'section':'third'},{'color': 'blue', 'section':'second'}]
My current solution:
sortedList = []
for section in orderList:
for item in dataList:
if item['section'] == section: sortedList.append(item)
Is there a cleaner way I can be sorting this?
Upvotes: 2
Views: 230
Reputation: 133764
>>> dicts = [{'color':'yellow', 'section':'third'},{'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
>>> L = ['first', 'third', 'second']
>>> order = dict(zip(L, range(len(L)))) # Dictionary for O(1) lookup
>>> sorted(dicts, key=lambda d: order[d['section']])
[{'color': 'red', 'section': 'first'}, {'color': 'yellow', 'section': 'third'}, {'color': 'blue', 'section': 'second'}]
This method will be O(N) instead of O(N log N) for the sort:
>>> sorted_sections = ['first', 'third', 'second']
>>> dicts = [{'color':'yellow', 'section':'third'},{'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
>>> dict_by_section = {d['section']:d for d in dicts}
>>> [dict_by_section[section] for section in sorted_sections]
[{'color': 'red', 'section': 'first'}, {'color': 'yellow', 'section': 'third'}, {'color': 'blue', 'section': 'second'}]
Upvotes: 3
Reputation: 471
orderList = ['first', 'third', 'second']
dataList = [{'color':'yellow', 'section':'third'},{'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
orderDict = dict((v,offset) for offset, v in enumerate(orderList))
print sorted(dataList, key=lambda d: orderDict[d['section']])
Upvotes: 0
Reputation: 10489
here is a more optimised version for you:
sort_key = lambda x: ks.index(x['section'])
print(sorted(dicts, key=sort_key))
Upvotes: 2
Reputation: 32308
You can use the built in sorted
function.
>>> lst = ['first', 'third', 'second']
>>> dcts = [{'color':'yellow', 'section':'third'}, {'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
>>> sorted(dcts, key=lambda dct: lst.index(dct['section']))
[{'section': 'first', 'color': 'red'}, {'section': 'third', 'color': 'yellow'}, {'section': 'second', 'color': 'blue'}]
Upvotes: 3
Reputation: 500923
You could just use sorted()
with key
:
In [6]: o = ['first', 'third', 'second']
In [7]: l = [{'color':'yellow', 'section':'third'},{'color':'red', 'section':'first'}, {'color': 'blue', 'section':'second'}]
In [8]: sorted(l, key=lambda x:o.index(x['section']))
Out[8]:
[{'color': 'red', 'section': 'first'},
{'color': 'yellow', 'section': 'third'},
{'color': 'blue', 'section': 'second'}]
This does a linear search on o
. If o
can be large, @jamylak's solution should be preferred.
Upvotes: 2