2

I have a dictionary like:

{'sortingOrder': ['da','ub','ac','rd'], 'listToSort': [{_id:'ub'}, {_id: 'da'}, {_id: 'rd'}, {_id: 'ac'}]}

I want to sort this list so that the id in listToSort matches how sortingOrder is sorted

[{_id:'da'}, {_id: 'ub'}, {_id: 'ac'}, {_id: 'rd'}] 

I have to compare a value from listToSort with a value from sortingOrder and sort listToSort accordingly, which has been my main issue.

The id can be any type of character, it just needs to be sorted the same way sortingOrder is sorted.

Sample of the file I have to sort by section title:

{
"storeOrder": ["produce", "bread", "spreads", "deli", "dairy"],
"itemList": [
    {
        "_id": 9, 
        "amountNumber": 1, 
        "amountStr": "2 loaves", 
        "amountUnits": null, 
        "estPrice": null, 
        "listId": 3, 
        "modified": "2010-10-26 18:11:58", 
        "name": "white bread", 
        "notes": null, 
        "price": null, 
        "section": "bread", 
        "status": 1
    }, 
    {
        "_id": 12, 
        "amountNumber": 1, 
        "amountStr": "1 jar", 
        "amountUnits": null, 
        "estPrice": null, 
        "listId": 3, 
        "modified": "2010-10-26 18:11:58", 
        "name": "raspberry jam", 
        "notes": "large bottle", 
        "price": null, 
        "section": "spreads", 
        "status": 0
    }
}
2
  • Is it possible for multiple items in your itemList to share a section value? In that case, is there a secondary sorting field (like name for example)? Commented Mar 22, 2016 at 18:54
  • Yes it is. If they are the same, name will be used to sort. Ideally this would be a stable sort Commented Mar 22, 2016 at 19:06

3 Answers 3

2

You can make an intermediary dict mapping index to string and use that to sort the list of id's:

d1 = {'sortingOrder': ['da','ub','ac','rd'], 'listToSort': [{"id":'ub'}, {"id": 'da'}, {"id": 'rd'}, {"id": 'ac'}]}

l = d1['listToSort']

sort_keys = {s: i for i, s in enumerate(d1["sortingOrder"])}

print(sorted(l, key=lambda d: sort_keys[d["id"]]))
[{'id': 'da'}, {'id': 'ub'}, {'id': 'ac'}, {'id': 'rd'}]

The dicts in l will be ordered by where their values appear in the "sortingOrder" list.

If you want to sort the list inplace so the original list is sorted just use list.sort:

  l.sort(key=lambda d: sort_keys[d["id"]])

If you want to break ties in your actual data by name then use the name as the secondary key to sort by:

   key=lambda d: (sort_keys[d["id"]], d["name"])
Sign up to request clarification or add additional context in comments.

Comments

1

You can sort a list of dictionaries (or any object) using one of their attributes or fields by using the key parameter to sort. The key parameter expects a function. Each element in the list will be passed to this function, and the return value will be used to sort the elements. In this case, we can create a simple function with lambda, which enables us to do everything in a single line.

d = {'sortingOrder': ['da','ub','ac','rd'], 'listToSort': [{id:'ub'}, {id: 'da'}, {id: 'rd'}, {id: 'ac'}]}

d['listToSort'].sort(key=lambda x: d['sortingOrder'].index(x['id']))

The one caveat is that it requires that every id value actually exists in the sortingOrder list, or else it will throw a ValueError.

Based off your update, you can sort a list of dictionaries on multiple fields by returning a tuple of the sort fields fron the key function for sort

d['itemList'].sort(key=lambda x: (d['storeOrder'].index(x['section']), x['name']))

Comments

1

If I understood your task correctly you could just recreate a list. Something like:

_id = xrange(4)
a = {'sortingOrder': ['da','ub','ac','rd'], 'listToSort': [{_id[0]:'ub'}, {_id[1]: 'da'}, {_id[2]: 'rd'}, {_id[3]: 'ac'}]}
arr = [{i.keys()[0]:e} for e in a['sortingOrder'] for i in a['listToSort'] if i.values()[0] == e  ]
a['listToSort'] = arr
print a['listToSort']

output

[{1: 'da'}, {0: 'ub'}, {3: 'ac'}, {2: 'rd'}]

UPDATE

a = {'sortingOrder': ['da','ub','ac','rd'], 'listToSort': [{'SortingKey':'ub'}, {'SortingKey': 'da'}, {'SortingKey': 'rd'}, {'SortingKey': 'ac'}]}
arr = [i for e in a['sortingOrder'] for i in a['listToSort'] if i['SortingKey'] == e  ]

5 Comments

Will this work if there are multiple values in the dictionary with the id's? for example if each id identified the model and you also had a serial number with the model number.
@Giovanni Could you add short example with input data to your question?
I put a small part of the file that needs to be sorted.
@Giovanni Please, see updated answer. dict in listToSort could contains any others keys.
I didn't downvote it. But now my question has been downvoted... no idea why

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.