Sort list of dictionary lists in python

I have an object that is a list of dictionary lists:

myObject =[[{ "play": 5.00, "id": 1, "uid": "abc" }, \ { "play": 1.00, "id": 2, "uid": "def" }], \ [{ "play": 6.00, "id": 3, "uid": "ghi" }, \ { "play": 7.00, "id": 4, "uid": "jkl" }], \ [{ "play": 3.00, "id": 5, "uid": "mno" }, \ { "play": 1.00, "id": 6, "uid": "pqr" }]] 

I want to sort the list by the sum of the play values ​​in the dictionaries of each nested list. Then the object will be sorted as follows:

 myObject =[[{ "play": 6.00, "id": 3, "uid": "ghi" }, \ { "play": 7.00, "id": 4, "uid": "jkl" }], \ [{ "play": 5.00, "id": 1, "uid": "abc" }, \ { "play": 1.00, "id": 2, "uid": "def" }], \ [{ "play": 3.00, "id": 5, "uid": "mno" }, \ { "play": 1.00, "id": 6, "uid": "pqr" }]] 

If it were just a list of dicts, then:

sorted(myObject, key=sum(map(itemgetter(play))), reverse=True)

will work. I cannot figure out how to do this without iterating over the list, calculating the sum, and then sorting. This is what I am doing now, but I am trying to increase the efficiency of this code by deleting loops, because my list has 100 million lists.

+5
source share
1 answer

Your idea is already very good to use a custom key function when sorting and using sum , map and itemgetter in play :

 key=sum(map(itemgetter(play))) 

You have a problem though: the key argument expects a function that takes an element of your list that you are sorting. But neither sum nor map returns a function, so you cannot use it as a key function. Instead, you can create a lambda function that performs this combination for each element.

Other problems are that play should be the string 'play' instead, and that map should accept subwords as an argument. So your key function would look like this:

 key=lambda x: sum(map(itemgetter('play'), x)) 

This is the way. functionally equivalent to the following understanding of a generator, which may be more readable:

 key=lambda x: sum(y['play'] for y in x) 

Using this with sorted should work, but you should consider sorting the list directly with list.sort :

 >>> myObject = [[{ "play": 5.00, "id": 1, "uid": "abc" }, { "play": 1.00, "id": 2, "uid": "def" }], [{ "play": 6.00, "id": 3, "uid": "ghi" }, { "play": 7.00, "id": 4, "uid": "jkl" }], [{ "play": 3.00, "id": 5, "uid": "mno" }, { "play": 1.00, "id": 6, "uid": "pqr" }]] >>> myObject.sort(key=lambda x: sum(y['play'] for y in x), reverse=True) >>> for x in myObject: print(x) [{'play': 6.0, 'uid': 'ghi', 'id': 3}, {'play': 7.0, 'uid': 'jkl', 'id': 4}] [{'play': 5.0, 'uid': 'abc', 'id': 1}, {'play': 1.0, 'uid': 'def', 'id': 2}] [{'play': 3.0, 'uid': 'mno', 'id': 5}, {'play': 1.0, 'uid': 'pqr', 'id': 6}] 

(Btw. MyObject is a bad name for a list of things.)


Regarding the effectiveness or complexity of your problem, you really cannot avoid having to scroll through each sublist ultimately. It is impossible to determine the sum of these values ​​without looking at the values, so obviously you cannot avoid it.

However, you must ensure that each amount is calculated only once to avoid having to view items in the sublists more than once. Fortunately, default sorting using list.sort accurately ensures that:

The key corresponding to each element in the list is calculated once, and then used for the entire sorting process.

This way you will have a very effective solution to this sorting problem.

+4
source

Source: https://habr.com/ru/post/1244070/


All Articles