注意:我不确定我应该在这里还是在CodeGolf上问这个问题,所以我会在这里发布,以防合适。
我正试图使用以下格式的lambdas在python中制作一个for循环:
x = 10
y = range(10)
w = 2
for g in range(w*w, x, w):
y[g] = 0
print y
这将输出正确的列表CCD_ 1。但是,我无法通过使用lambdas来更改列表。我的代码是:
print(lambda w,x=10,y=range(10): (map(lambda g: (lambda f=y.__setitem__: (f(g,0) )()), range(w*w,x,w)), y))(2)
"""
w is the step value in the for loop, which is 2
x is the size of the list, 10
y is the list, range(10)
lambda g is the first argument for map as the function. It sets the value of the list y at the current index g to be 0, through the use of lambda f's setitem
range(w*w,x,w) is the second argument passed to map as an iterable. In theory, all the indexes of y in this list should be set to 0 through the use of lambda f
y is returned to be printed
2 is the value passed to w
"""
但是,这会返回错误的[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
。有人知道我如何在一句话中做到这一点吗?我应该使用其他内置函数在lambda中进行循环吗?我用这个和这个作为参考,以防有帮助。
可能更容易使用列表综合:
print (lambda w, x=10, y=range(10):
[(0 if (i >= w*w and i < x and i%w==0) else n) for i, n in enumerate(y)])(2)
为了可读性,移动到两行,但您可以删除\和换行符,它会运行良好。
需要注意的是,这不会更改原始列表,而是返回一个新列表。
如果你需要它来更新原始列表并返回它,你可以使用短路:
print (lambda w, x=10, y=range(10):
([y.__setitem__(i, 0) for i in range(w*w, x, w)] and y))(2)
更正:
上面的代码仅在range(w*w, x, w)
不为空的情况下有效,即w*w > x
,这是一个弱条件。
以下更正了此问题:
print (lambda w, x=10, y=range(10):
(([y.__setitem__(i, 0) for i in range(w*w, x, w)] or 1) and y))(2)
这使用了这样一个事实,即在a
的值被求值之后,(a or 1) and b
总是求值为b
。
这里有一个纯lambda
实现,它将w
、[0, 1, 2, 3, 0, 5, 0, 7, 0, 9]
0和y
作为顶级lambda
:的参数
>>> (lambda w,x,y: (lambda s: map(lambda v: 0 if v in s else v, y))(set(range(w*w,x,w))))(2,10,range(10))
[0, 1, 2, 3, 0, 5, 0, 7, 0, 9]
>>>
请注意,这避免了使用__setitem__
。
使用map
的副作用是令人憎恶的,但是:
>>> x = 10
>>> y = range(10)
>>> w = 2
>>> map(lambda i: y.__setitem__(i, 0), range(w*w, x, w))
[None, None, None]
>>> y
[0, 1, 2, 3, 0, 5, 0, 7, 0, 9]
一个不太令人反感的方法是使用切片分配
>>> y = range(10)
>>> y[w*w: x: w] = [0]*len(range(w*w, x, w))
>>> y
[0, 1, 2, 3, 0, 5, 0, 7, 0, 9]