以下 Common Lisp 代码在 python 中的等效列表理解是什么:
(loop for x = input then (if (evenp x)
(/ x 2)
(+1 (* 3 x)))
collect x
until (= x 1))
以下 Common Lisp 代码在 python 中的等效列表理解是什么:
(loop for x = input then (if (evenp x)
(/ x 2)
(+1 (* 3 x)))
collect x
until (= x 1))
列表推导式用于获取现有序列并对其执行某些功能和/或过滤,从而产生一个新列表。因此,在这种情况下,列表推导是不合适的,因为您没有起始序列。带有 while 循环的示例:
numbers = []
x=input()
while x != 1:
numbers.append(x)
if x % 2 == 0: x /= 2
else: x = 3 * x + 1
我相信你正在编写冰雹序列,尽管我可能是错的,因为我不流利地使用 Lisp。
据我所知,您不能仅在列表理解中执行此操作,因为每个元素都依赖于最后一个元素。
我会怎么做
def hailstone(n):
yield n
while n!=1
if n%2 == 0: # even
n = n / 2
else: # odd
n = 3 * n + 1
yield n
list = [ x for x in hailstone(input) ]
当然,输入将保留您的输入。
我的冰雹功能可能更简洁。我的目标是清晰。
劳伦斯提到的黑客:
您可以在一个列表理解中做到这一点,它最终会成为 AWFUL python。不可读的蟒蛇。可怕的蟒蛇。我只是出于好奇而提出以下内容,而不是作为实际答案。不要在你真正想要使用的代码中这样做,只有当你想玩一下 python 的内部工作时。
所以,3种方法:
1:使用帮助列表,答案最终出现在帮助列表中。这会将值附加到正在迭代的列表中,直到您达到要停止的值。
A = [10]
print [None if A[-1] == 1
else A.append(A[-1]/2) if (A[-1]%2==0)
else A.append(3*A[-1]+1)
for i in A]
print A
结果:
[None, None, None, None, None, None, None]
[10, 5, 16, 8, 4, 2, 1]
2:使用帮助列表,但结果是列表理解的输出。这主要依赖于为算术目的list.append(...)
返回None
、not None
评估True
和True
考虑1
。叹。
A=[10]
print [A[0]*(not A.append(A[0])) if len(A) == 1
else 1 if A[-1] == 2 else (A[-1]/2)*(not A.append(A[-1]/2)) if (A[-1]%2==0)
else (3*A[-1]+1)*(not A.append(3*A[-1]+1))
for i in A]
结果:
[10, 5, 16, 8, 4, 2, 1]
3:不使用帮助列表,而是在构建列表时引用它。这有点脆弱,可能不适用于所有环境。如果它不起作用,请尝试自行运行代码:
from itertools import chain, takewhile
initialValue = 10
print [i if len(locals()['_[1]']) == 0
else (locals()['_[1]'][-1]/2) if (locals()['_[1]'][-1]%2==0)
else (3*locals()['_[1]'][-1]+1)
for i in takewhile(lambda x:x>1, chain([initialValue],locals()['_[1]']))]
结果:
[10, 5, 16, 8, 4, 2, 1]
所以,现在忘记你读过这个。这是一条黑暗、黑暗和肮脏的蟒蛇。邪恶的蟒蛇。我们都知道蟒蛇并不邪恶。Python 很可爱。所以你不可能读过这个,因为这种东西不可能存在。好好。
Python 没有内置这种控制结构,但您可以将其概括为如下函数:
def unfold(evolve, initial, until):
state = initial
yield state
while not until(state):
state = evolve(state)
yield state
在此之后,您的表达式可以写成:
def is_even(n): return not n % 2
unfold(lambda x: x/2 if is_even(x) else 3*x + 1,
initial=input, until=lambda x: x == 1)
但是 Pythonic 的方法是使用生成器函数:
def produce(x):
yield x
while x != 1:
x = x / 2 if is_even(x) else 3*x + 1
yield x
正如 Kiv 所说,列表推导需要一个已知的序列来迭代。
话虽如此,如果您有一个序列并且专注于使用列表推导,您的解决方案可能包括以下内容:
[not (x % 2) and (x / 2) or (3 * x + 1) for x in sequence]
迈克库珀的回答是一个更好的解决方案,因为它都保留了x != 1
终止,而且这一行读起来不干净。
1
我发现了一个真正奇妙的证明,这个空白太窄而无法包含。
不过说真的,我不相信你可以用 Python 列表推导来做到这一点。它们与 map 和 filter 具有基本相同的功能,因此您无法在不求助于骇客的情况下突破或查看以前的值。