2

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?

2
  • Are you guaranteed to only have one color for each section? Commented Mar 28, 2013 at 9:21
  • There may be more attributes, but they are all unique keys referencing a single string. Commented Mar 28, 2013 at 9:23

5 Answers 5

3

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'}]
Sign up to request clarification or add additional context in comments.

Comments

3
>>> 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'}]

5 Comments

The .index approaches work fine for small sizes but using a dict will scale better.
There are two problems with this "optimization". First, building a helper dict is O(n), second, it requires twice as much memory.
@thg435 I don't see those as problems. Also it won't require twice as much memory since it's only storing references to each dictionary.
@DivinusVox Yeah but that's why I asked if they would exist or not and you said they were all unique keys. Anyway it's all good
@jamylak Aha, I misread your original comment. My bad. Thanks for the help.
2

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.

Comments

2

here is a more optimised version for you:

sort_key = lambda x: ks.index(x['section'])

print(sorted(dicts, key=sort_key))

Comments

0
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']])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.