是否有可能在Python lambdaexpression式中有多个语句?
我是一个python新手试图达到以下目的:
我有一个列表清单:
lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]]
我想把lst映射到另一个只包含每个子列表中次数最less的列表。 所以结果应该是:
[345, 465, 333]
例如,如果我只是对最小的数字感兴趣,我可以这样做:
map(lambda x: min(x),lst)
我希望我能做到这一点:
map(lambda x: sort(x)[1],lst)
但sorting不连锁。 (返回None)
既不是这样允许的:
map(lambda x: sort(x); x[1],lst) #hence the multiple statement question
有没有办法做到这一点在Python中的地图,但没有定义一个命名函数 ? (比如用ruby中的匿名块很容易)
我可以给出几个不同的答案,从你的具体问题到更普遍的问题。 所以从最具体到最一般:
问:你可以把多个语句放入lambda?
答:不,但实际上你不需要使用lambda。 您可以将语句放在def
。 即:
def second_lowest(l): l.sort() return l[1] map(second_lowest, lst)
问:你能通过sorting列表从lambda中获得第二个最低的项目吗?
答:是的。 正如alex的答案指出的那样, sorted()
是创build新列表的sorting版本,而不是就地sorting,并且可以被链接。 请注意,这可能是你应该使用的 – 对于你的地图在原始列表上有副作用是不好的做法。
问:我应该如何从列表中的每个列表中获得第二低的项目。
A. sorted(l)[1]
实际上并不是最好的办法。 它具有O(N log(N))复杂度,而O(n)解存在。 这可以在heapq模块中find。
>>> import heapq >>> l = [5,2,6,8,3,5] >>> heapq.nsmallest(l, 2) [2, 3]
所以只需使用:
map(lambda x: heapq.nsmallest(x,2)[1], list_of_lists)
使用列表理解通常也被认为更清晰,这完全避免了lambda:
[heapq.nsmallest(x,2)[1] for x in list_of_lists]
将这些语句放在一个列表中可以模拟多个语句:
例如:
lambda x: [f1(x), f2(x), f3(x), x+1]
时间旅行在这里。 如果您通常希望在lambda中包含多个语句,则可以将其他lambda作为parameter passing给该lambda。
(lambda x, f: list((y[1] for y in f(x))))(lst, lambda x: (sorted(y) for y in x))
你实际上不能有多个语句,但是你可以通过传递lambdaexpression式来模拟lambdaexpression式。
编辑:时间旅行者回报! 您也可以滥用布尔expression式的行为(记住短路规则和真实性)来链式操作。 使用三元运算符可以为您提供更多的function。 同样,你不能有多个语句 ,但你当然可以有很多的函数调用。 这个例子用一堆数据做一些随意的垃圾,但是,这表明你可以做一些有趣的事情。 print语句是返回None
的函数的示例(与.sort()
方法一样),但是它们也帮助显示lambda
正在做什么。
>>> (lambda x: print(x) or x+1)(10) 10 11 >>> f = (lambda x: x[::2] if print(x) or x.sort() else print(enumerate(x[::-1]) if print(x) else filter(lambda (i, y): print((i, y)) or (i % 3 and y % 2), enumerate(x[::-1])))) >>> from random import shuffle >>> l = list(range(100)) >>> shuffle(l) >>> f(l) [84, 58, 7, 99, 17, 14, 60, 35, 12, 56, 26, 48, 55, 40, 28, 52, 31, 39, 43, 96, 64, 63, 54, 37, 79, 25, 46, 72, 10, 59, 24, 68, 23, 13, 34, 41, 94, 29, 62, 2, 50, 32, 11, 97, 98, 3, 70, 93, 1, 36, 87, 47, 20, 73, 45, 0, 65, 57, 6, 76, 16, 85, 95, 61, 4, 77, 21, 81, 82, 30, 53, 51, 42, 67, 74, 8, 15, 83, 5, 9, 78, 66, 44, 27, 19, 91, 90, 18, 49, 86, 22, 75, 71, 88, 92, 33, 89, 69, 80, 38] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] (0, 99) (1, 98) (2, 97) (3, 96) (4, 95) (5, 94) (6, 93) (7, 92) (8, 91) (9, 90) (10, 89) (11, 88) (12, 87) (13, 86) (14, 85) (15, 84) (16, 83) (17, 82) (18, 81) (19, 80) (20, 79) (21, 78) (22, 77) (23, 76) (24, 75) (25, 74) (26, 73) (27, 72) (28, 71) (29, 70) (30, 69) (31, 68) (32, 67) (33, 66) (34, 65) (35, 64) (36, 63) (37, 62) (38, 61) (39, 60) (40, 59) (41, 58) (42, 57) (43, 56) (44, 55) (45, 54) (46, 53) (47, 52) (48, 51) (49, 50) (50, 49) (51, 48) (52, 47) (53, 46) (54, 45) (55, 44) (56, 43) (57, 42) (58, 41) (59, 40) (60, 39) (61, 38) (62, 37) (63, 36) (64, 35) (65, 34) (66, 33) (67, 32) (68, 31) (69, 30) (70, 29) (71, 28) (72, 27) (73, 26) (74, 25) (75, 24) (76, 23) (77, 22) (78, 21) (79, 20) (80, 19) (81, 18) (82, 17) (83, 16) (84, 15) (85, 14) (86, 13) (87, 12) (88, 11) (89, 10) (90, 9) (91, 8) (92, 7) (93, 6) (94, 5) (95, 4) (96, 3) (97, 2) (98, 1) (99, 0) [(2, 97), (4, 95), (8, 91), (10, 89), (14, 85), (16, 83), (20, 79), (22, 77), (26, 73), (28, 71), (32, 67), (34, 65), (38, 61), (40, 59), (44, 55), (46, 53), (50, 49), (52, 47), (56, 43), (58, 41), (62, 37), (64, 35), (68, 31), (70, 29), (74, 25), (76, 23), (80, 19), (82, 17), (86, 13), (88, 11), (92, 7), (94, 5), (98, 1)]
使用sorting函数 ,如下所示:
map(lambda x: sorted(x)[1],lst)
或者,如果你想避免lambda,并有一个生成器,而不是一个列表:
(sorting(col)[1] col in lst)
从这里使用begin(): http : //www.reddit.com/r/Python/comments/hms4z/ask_pyreddit_if_you_were_making_your_own/c1wycci
Python 3.2 (r32:88445, Mar 25 2011, 19:28:28) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> lst = [[567,345,234],[253,465,756, 2345],[333,777,111, 555]] >>> begin = lambda *args: args[-1] >>> list(map(lambda x: begin(x.sort(), x[1]), lst)) [345, 465, 333]
你实际上可以在python的lambdaexpression式中有多个语句。 这不是微不足道的,但在你的例子中,以下工作:
map(lambda x: x.sort() or x[1],lst)
你必须确保每个语句不返回任何东西,或者如果它包含在(..和False)中。 结果是上次评估返回的结果。
例:
>>> f = (lambda : (print(1) and False) or (print(2) and False) or (print(3) and False)) >>> f() 1 2 3
在python中将多个语句组合成单个语句的方法是使用“和”关键字作为短路操作符。 那么你可以直接使用这个单一语句作为lambdaexpression式的一部分。
这与使用“&&”作为诸如bash之类的shell语言中的短路操作符类似。
还要注意:你可以通过包装函数来修改一个函数语句来返回一个真正的值。
例:
def p2(*args): print(*args) return 1 # a true value junky = lambda x, y: p2('hi') and p2('there') and p2(x) and p2(y) junky("a", "b")
第二个想法,它可能更好地使用“或”而不是“和”,因为许多函数成功返回0或无。 那么你可以去掉上面例子中的包装函数:
junky = lambda x, y: print('hi') or print('there') or print(x) or print(y) junky("a", "b")
'和'操作将评估expression式,直到达到第一个零返回值。 之后它短路。 1和1以及0和1评估:1和1和0,并且下降1
'或'操作将评估expression式,直到达到第一个非零返回值。 之后它短路。
0或0或1或0评估0或0或1,然后下降0
你可以在O(n)时间使用min和index来代替sort或heapq。
首先创build除原始列表的最小值以外的所有内容的新列表:
new_list = lst[:lst.index(min(lst))] + lst[lst.index(min(lst))+1:]
然后取新的列表的最小值:
second_smallest = min(new_list)
现在所有在一起的lambda:
map(lambda x: min(x[:x.index(min(x))] + x[x.index(min(x))+1:]), lst)
是的,这真的很丑,但它应该是algorithm便宜。 也因为这个线程中的一些人想看到列表parsing:
[min(x[:x.index(min(x))] + x[x.index(min(x))+1:]) for x in lst]
这正是Monad中的bind
函数所使用的。
使用bind
函数,可以将多个lambda组合成一个lambda,每个lambda表示一个语句。
我会给你另一个解决scheme,让你的lambda调用一个函数。
def multiple_statements(x, y): print('hi') print('there') print(x) print(y) return 1 junky = lambda x, y: multiple_statements(x, y) junky('a', 'b');
让我向你展示一个可怕而可怕的黑客:
import types def _obj(): return lambda: None def LET(bindings, body, env=None): '''Introduce local bindings. ex: LET(('a', 1, 'b', 2), lambda o: [oa, ob]) gives: [1, 2] Bindings down the chain can depend on the ones above them through a lambda. ex: LET(('a', 1, 'b', lambda o: oa + 1), lambda o: ob) gives: 2 ''' if len(bindings) == 0: return body(env) env = env or _obj() k, v = bindings[:2] if isinstance(v, types.FunctionType): v = v(env) setattr(env, k, v) return LET(bindings[2:], body, env)
您现在可以使用这个LET
表单:
map(lambda x: LET(('_', x.sort()), lambda _: x[1]), lst)
这给出: [345, 465, 333]