Modify Python sorted() build-in func to return a list with values from lambda

Viewed 2332

Given a python list:

nums = [9,4,5,7,-1,2,-3,0]

The task is to write a function that will return a new list with squares of numbers of original list in ascending order. Expected output:

[0, 1, 4, 9, 16, 25, 49, 81]

The simplest way to do this is just create a new list and then apply Python build-in sorted() function:

def my_sort(nums):
    new_list = [i**2 for i in nums]
    return sorted(new_list)

print(my_sort(nums))

output as expected:

[0, 1, 4, 9, 16, 25, 49, 81]

However there is another option is to use "key" argument and pass lambda function inside sorted():

new_list = sorted(nums, key=lambda x: x**2)
print(new_list)

output:

[0, -1, 2, -3, 4, 5, 7, 9]

Here we have the same sorting behavior with difference that sorted() function return sorted list with original values.

My question - is there any way to override python build-in sorted() function that it will return a sored list with values from lambda?

UPD:

Apparently i have to explain a little where this question came from, for greater clarity. I had a python interview where this question was asked. When i implemented my basic solution, the interviewer said that in terms of big O() complexity, this solution is not entirely effective, arguing that fisrt we create a new array\list at the beginning and only then apply sorting algorithm over it and suggested writing sorting "on the fly". I was confused because believed that there was no point in writing a custom sorting algorithm and no doubt it will perform slower than the built-in solution, i woud never write my own "Timesort" algorithm (which as i kwon implemented in sorted()). Later, thinking about this question, there was a suggestion that a solution with sorting via a key would perform faster than sorting with the preliminary creation of a new list. Therefore, this question arose. However, further tests showed that soution when we create a new list works faster than sorting through the key=lambda function. But of course, this is beyond the scope of this question.

4 Answers

is there any way to override python build-in sorted() function that it will return a sored list with values from lambda?

Sorry, but this is the WrongWayToIt™. It fights how the tools were designed to be used. Instead, the right way is to convert the data first and then sort it:

>>> nums = [9,4,5,7,-1,2,-3,0]
>>> sorted(map(lambda x: x**2, nums))
[0, 1, 4, 9, 16, 25, 49, 81]

If for some reason you still have to rewrite sorted(), follow essentially same pattern in the new function:

>>> def new_sorted(data, key):
...     return sorted(map(key, data))
...

>>> new_sorted(nums, key=lambda x: x*x)
[0, 1, 4, 9, 16, 25, 49, 81]

You have got it all wrong. That's not how the key parameter is supposed to work. The value of the key parameter should be a function (or other callable) that takes a single argument and returns a key to use for sorting purposes.

That's why you are getting the original values.

See the docs: https://docs.python.org/3.12/howto/sorting.html

You can do it by importing builtins module to use original sorted method and write your own in current scope

import builtins
def sorted(l,/, *, key=None, reverse=False, f=None):
    bsorted = builtins.sorted
    if f is None:
        return bsorted(l, key=key, reverse=reverse)
    else:
        l = [f(x) for x in l]
    return bsorted(l, key=key, reverse=reverse)

However you are overwriting a well-known builtin method to add new functionality, which could cause confusion when other people read your code. You should better use another name instead of doing it.

You can replace the original sorted function globally by setting builtins.sorted. my_own_sorted is your own implementation.

import builtins
builtins.sorted = my_own_sorted
Related