0

I am trying to mess around with lambda functions in regards to lists, and i am wondering whether it is possible to optimize this code:

print(max([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], key=lambda x: x if x<9 else 0))

This code-snip does indeed work, but i wonder whether there is a way to remove the else-part in the lambda function itself, as this seems to be a necessary "parameter". I am very well aware that i could just use a list comprehension like [i for i in arr if i<9], but i am looking for solutions to this specific function.

I am using Python 3.10.6.

I have tried several ways to rewrite the lambda function, but i keep getting the error that i need the else-part.

Atlas
  • 11
  • 3

2 Answers2

0

You can simplify the lambda function in your code by using the max() function within the lambda function to compare the value with 9

print(max([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], key=lambda x: x if x < 9 else max([0, x])))
godot
  • 3,422
  • 6
  • 25
  • 42
0

Yes, there's always an uglier way.

In the background you're simply creating an 1:1 mapping, that's why the else-less variant protests:

[x if x<9 else 0 for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

produces

[1, 2, 3, 4, 5, 6, 7, 8, 0, 0]

as output, so still there are 10 elements.
While

[x if x<9 for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

doesn't even work, because a single condition (different construct) comes at the end, but

[x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] if x<9]

would produce 8 elements only:

[1, 2, 3, 4, 5, 6, 7, 8]

So if you look at this intermediate step, it may be more visible why the else part is required: you need an expression, which produces a result for every case, and not a yes/no condition.

And the ugly part: with the signum function (which doesn't exist in Python for historical reasons), and some truncation of it (to 0-1), it's possible to create an if-else-less mathematical expression, but for sure it's not looking better than your original:

[x-x*max(math.copysign(1,x-9),0) for x in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]

results in

[1, 2, 3, 4, 5, 6, 7, 8, 0.0, 0.0]

And then of course it works with the original code too:

print(max([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], key=lambda x: x-x*max(math.copysign(1,x-9),0)))
tevemadar
  • 12,389
  • 3
  • 21
  • 49