There are several different answers I can give here, from your specific question to more general concerns. So from most specific to most general:
Q. Can you put multiple statements in a lambda?
A. No. But you don't actually need to use a lambda. You can put the statements in a def instead. i.e.:
def second_lowest(l):
l.sort()
return l[1]
map(second_lowest, lst)
Q. Can you get the second lowest item from a lambda by sorting the list?
A. Yes. As alex's answer points out, sorted() is a version of sort that creates a new list, rather than sorting in-place, and can be chained. Note that this is probably what you should be using - it's bad practice for your map to have side effects on the original list.
Q. How should I get the second lowest item from each list in a sequence of lists?
A. sorted(l)[1] is not actually the best way for this. It has O(N log(N)) complexity, while an O(n) solution exists. This can be found in the heapq module.
>>> import heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]
So just use:
map(lambda x: heapq.nsmallest(x,2)[1], list_of_lists)
It's also usually considered clearer to use a list comprehension, which avoids the lambda altogether:
[heapq.nsmallest(x,2)[1] for x in list_of_lists]
Answer from Brian on Stack OverflowThere are several different answers I can give here, from your specific question to more general concerns. So from most specific to most general:
Q. Can you put multiple statements in a lambda?
A. No. But you don't actually need to use a lambda. You can put the statements in a def instead. i.e.:
def second_lowest(l):
l.sort()
return l[1]
map(second_lowest, lst)
Q. Can you get the second lowest item from a lambda by sorting the list?
A. Yes. As alex's answer points out, sorted() is a version of sort that creates a new list, rather than sorting in-place, and can be chained. Note that this is probably what you should be using - it's bad practice for your map to have side effects on the original list.
Q. How should I get the second lowest item from each list in a sequence of lists?
A. sorted(l)[1] is not actually the best way for this. It has O(N log(N)) complexity, while an O(n) solution exists. This can be found in the heapq module.
>>> import heapq
>>> l = [5,2,6,8,3,5]
>>> heapq.nsmallest(l, 2)
[2, 3]
So just use:
map(lambda x: heapq.nsmallest(x,2)[1], list_of_lists)
It's also usually considered clearer to use a list comprehension, which avoids the lambda altogether:
[heapq.nsmallest(x,2)[1] for x in list_of_lists]
Putting the expressions in a list may simulate multiple expressions:
E.g.:
lambda x: [f1(x), f2(x), f3(x), x+1]
This will not work with statements.
Sure:
List<String> items = new List<string>();
var results = items.Where(i =>
{
bool result;
if (i == "THIS")
result = true;
else if (i == "THAT")
result = true;
else
result = false;
return result;
}
);
(I'm assuming you're really talking about multiple statements rather than multiple lines.)
You can use multiple statements in a lambda expression using braces, but only the syntax which doesn't use braces can be converted into an expression tree:
// Valid
Func<int, int> a = x => x + 1;
Func<int, int> b = x => { return x + 1; };
Expression<Func<int, int>> c = x => x + 1;
// Invalid
Expression<Func<int, int>> d = x => { return x + 1; };
Can a lambda expression truly contain multiple statements?
What are some common uses of lambda expressions?
Why can't I use the `sort` method directly in a lambda?
sys.stdout.write("second") is not part of the lambda.
'second' is always printed even if you don't call X. In other words calling X only prints 'first'.
Your code can be rewritten as;
import sys
X = lambda: sys.stdout.write('first')
sys.stdout.write("second")
print X()
If you want two statements executed by the lambda place them in a tuple;
lambda: (sys.stdout.write('first'),sys.stdout.write("second"))
The syntax for lambda is:
lambda <args>: <expression>
where <expression> must be a single expression. It cannot be a statement, or multiple statements, or multiple expressions separated by ;.
What happens in your code is that lambda has higher priority over ;, so that gets parsed as: X = lambda: sys.stdout.write('first') followed by sys.stdout.write("second"). Adding parentheses around sys.stdout.write('first') ; sys.stdout.write("second") would not work and produce a syntax error.
My trick to do multiple things inside a lambda is:
f = lambda: [None, sys.stdout.write('first'), sys.stdout.write("second")][0]
and the other one:
f = lambda: [None, sys.stdout.write("..."), sys.exit(0)][0]
However that kind of defeats the purpose of a lambda function, which is to do something short and really simple.
I guess that would still be OK in your specific example, but kind of looks like a hack.
I'm assuming the method of the functional interface implemented by this lambda expression has a return value, so when using brackets, it should include a return statement, just like any method with non-void return type.
new JdbcTemplate(new SingleConnectionDataSource(c, true))
.query("select id, name from PLAYERS", (rs, rowNum) ->
{
return new Player(rs.getString("id"), rs.getString("name");
})
);
Don't do that. Having multiple statements in a lambda in most cases is a code smell. Rather create a method with two parameters:
private Player toPlayer(ResultSet rs, int rowNum) {
// multiple setters here
return player;
}
And then pass the method reference (which in fact will behave like a BiFunction) instead of lambda:
new JdbcTemplate(new SingleConnectionDataSource(c, true))
.query("select id, name from PLAYERS", this::toPlayer);
One may want to create a static utility method instead of a dynamic one. The logic is the same as above:
public class MappingUtil {
// ...
public static Player toPlayer(ResultSet rs, int rowNum) {
// multiple setters here
return player;
}
}
And then:
new JdbcTemplate(new SingleConnectionDataSource(c, true))
.query("select id, name from PLAYERS", MappingUtil::toPlayer);