Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested lambda statements when sorting lists

I wish to sort the below list first by the number, then by the text.

lst = ['b-3', 'a-2', 'c-4', 'd-2']

# result:
# ['a-2', 'd-2', 'b-3', 'c-4']

Attempt 1

res = sorted(lst, key=lambda x: (int(x.split('-')[1]), x.split('-')[0]))

I was not happy with this since it required splitting a string twice, to extract the relevant components.

Attempt 2

I came up with the below solution. But I am hoping there is a more succinct solution via Pythonic lambda statements.

def sorter_func(x):
    text, num = x.split('-')
    return int(num), text

res = sorted(lst, key=sorter_func)

I looked at Understanding nested lambda function behaviour in python but couldn't adapt this solution directly. Is there a more succinct way to rewrite the above code?

like image 500
jpp Avatar asked Apr 05 '18 12:04

jpp


People also ask

How do you sort a list using lambda function?

The list. sort() method key parameter is set to lambda. The arguement x is the iterable element ( tuple ) to be sorted by the second element, the number. The lambda expression sorts the list by the second element of the tuple value and updates the original.

Can lambda functions be nested?

A lambda function inside a lambda function is called a nested lambda function. Python allows lambda nesting, i.e., you can create another lambda function inside a pre-existing lambda function. For nesting lambdas, you will need to define two lambda functions – an outer and an inner lambda function.

What is key lambda in sort Python?

The use of lambda creates an anonymous function (which is callable). In the case of sorted the callable only takes one parameters. Python's lambda is pretty simple. It can only do and return one thing really. The syntax of lambda is the word lambda followed by the list of parameter names then a single block of code.

How do you use lambda in Python sort function?

Use the list sort() method to sort a list with a lambda expression in Python. Just call the list. sort(key=None) with a key set to a lambda expression to sort the elements of the list by the key. Both list.


2 Answers

There are 2 points to note:

  • One-line answers are not necessarily better. Using a named function is likely to make your code easier to read.
  • You are likely not looking for a nested lambda statement, as function composition is not part of the standard library (see Note #1). What you can do easily is have one lambda function return the result of another lambda function.

Therefore, the correct answer can found in Lambda inside lambda.

For your specific problem, you can use:

res = sorted(lst, key=lambda x: (lambda y: (int(y[1]), y[0]))(x.split('-')))

Remember that lambda is just a function. You can call it immediately after defining it, even on the same line.

Note #1: The 3rd party toolz library does allow composition:

from toolz import compose

res = sorted(lst, key=compose(lambda x: (int(x[1]), x[0]), lambda x: x.split('-')))

Note #2: As @chepner points out, the deficiency of this solution (repeated function calls) is one of the reasons why PEP-572 is considered implemented in Python 3.8.

like image 195
jpp Avatar answered Oct 14 '22 18:10

jpp


We can wrap the list returned by split('-') under another list and then we can use a loop to handle it:

# Using list-comprehension
>>> sorted(lst, key=lambda x: [(int(num), text) for text, num in [x.split('-')]])
['a-2', 'd-2', 'b-3', 'c-4']
# Using next()
>>> sorted(lst, key=lambda x: next((int(num), text) for text, num in [x.split('-')]))
['a-2', 'd-2', 'b-3', 'c-4']
like image 20
Ashwini Chaudhary Avatar answered Oct 14 '22 16:10

Ashwini Chaudhary