Sorting based on custom sort key

237 views Asked by At

I have a python function that receives this 2 arguments:

list = [
            {"id": "5", "name": "tomato", "value": 3},
            {"id": "2", "name": "banana", "value": 2},
            {"id": "4", "name": "tomato", "value": 2},
            {"id": "1", "name": "banana", "value": 1.5},
            {"id": "8", "name": "peas", "value": 1.5},
            {"id": "7", "name": "peas", "value": 0.5}
        ]


"importance"={
            "tomato": 2,
            "banana": 1,
            "peas": 6
           }

I pre ordered the list based on value but now I want to order on the same value floor according to importance so it would look like in the end:

list = [
        {"id": "5", "name": "tomato", "value": 3},
        {"id": "4", "name": "tomato", "value": 2},
        {"id": "2", "name": "banana", "value": 2},
        {"id": "8", "name": "peas", "value": 1.5},
        {"id": "1", "name": "banana", "value": 1.5},
        {"id": "7", "name": "peas", "value": 0.5}
    ]

How can I do this using custom sort functions? Or is there any better way to do it?

2

There are 2 answers

1
matszwecja On BEST ANSWER

.sort and sorted functions accept a key argument, which can return a number or a tuple of numbers. Output will be sorted by first element of such tuple, then second etc. This way you can sort according to all the requirements you have.

l = [
            {"id": "5", "name": "tomato", "value": 3},
            {"id": "2", "name": "banana", "value": 2},
            {"id": "4", "name": "tomato", "value": 2},
            {"id": "1", "name": "banana", "value": 1.5},
            {"id": "8", "name": "peas", "value": 1.5},
            {"id": "7", "name": "peas", "value": 0.5}
        ]


importance = {
            "tomato": 2,
            "banana": 1,
            "peas": 6
           }

print(sorted(l, key = lambda x: (x["value"], importance[x["name"]]), reverse=True))

Output:

[
    {'id': '5', 'name': 'tomato', 'value': 3}, 
    {'id': '4', 'name': 'tomato', 'value': 2}, 
    {'id': '2', 'name': 'banana', 'value': 2}, 
    {'id': '8', 'name': 'peas', 'value': 1.5}, 
    {'id': '1', 'name': 'banana', 'value': 1.5}, 
    {'id': '7', 'name': 'peas', 'value': 0.5}
]

Note: With this code, there is no need to pre-sort according to just value first - both keys are taken into account.

0
SIGHUP On

Using a discrete function to return the sort key, you can do this:

import json

_list = [
    {"id": "5", "name": "tomato", "value": 3},
    {"id": "2", "name": "banana", "value": 2},
    {"id": "4", "name": "tomato", "value": 2},
    {"id": "1", "name": "banana", "value": 1.5},
    {"id": "8", "name": "peas", "value": 1.5},
    {"id": "7", "name": "peas", "value": 0.5}
]


importance = {
    "tomato": 2,
    "banana": 1,
    "peas": 6
}


def key(e):
    # use -ve values to avoid the need for reversing the sort
    return -e['value'], -importance[e['name']]


_list.sort(key=key)

print(json.dumps(_list, indent=2))

Output:

[
  {
    "id": "5",
    "name": "tomato",
    "value": 3
  },
  {
    "id": "4",
    "name": "tomato",
    "value": 2
  },
  {
    "id": "2",
    "name": "banana",
    "value": 2
  },
  {
    "id": "8",
    "name": "peas",
    "value": 1.5
  },
  {
    "id": "1",
    "name": "banana",
    "value": 1.5
  },
  {
    "id": "7",
    "name": "peas",
    "value": 0.5
  }
]