列表理解Python

发布于 2024-07-26 09:37:53 字数 227 浏览 6 评论 0原文

以下 Common Lisp 代码在 python 中的等效列表理解是什么:

(loop for x = input then (if (evenp x)
                             (/ x 2)
                             (+1 (* 3 x)))
      collect x
      until (= x 1))

What is the equivalent list comprehension in python of the following Common Lisp code:

(loop for x = input then (if (evenp x)
                             (/ x 2)
                             (+1 (* 3 x)))
      collect x
      until (= x 1))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

撑一把青伞 2024-08-02 09:37:53

列表理解用于获取现有序列并对其执行某些功能和/或过滤,从而生成一个新列表。 因此,在这种情况下,列表理解是不合适的,因为您没有起始序列。 一个 while 循环的例子:

numbers = []
x=input()
while x != 1:
  numbers.append(x)
  if x % 2 == 0: x /= 2
  else: x = 3 * x + 1

A list comprehension is used to take an existing sequence and perform some function and/or filter to it, resulting in a new list. So, in this case a list comprehension is not appropriate since you don't have a starting sequence. An example with a while loop:

numbers = []
x=input()
while x != 1:
  numbers.append(x)
  if x % 2 == 0: x /= 2
  else: x = 3 * x + 1
掌心的温暖 2024-08-02 09:37:53

我相信你正在写冰雹序列,尽管我可能是错的,因为我不流利的 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) ]

,输入将保存您的输入是什么。

我的冰雹函数可能会更简洁。 我的目标是清晰。

I believe you are writing the hailstone sequence, although I could be wrong since I am not fluent in Lisp.

As far as I know, you can't do this in only a list comprehension, since each element depends on the last.

How I would do it would be this

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) ]

Of course, input would hold whatever your input was.

My hailstone function could probably be more concise. My goal was clarity.

笑饮青盏花 2024-08-02 09:37:53

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

Python doesn't have this kind of control structure built in, but you can generalize this into a function like this:

def unfold(evolve, initial, until):
    state = initial
    yield state
    while not until(state):
        state = evolve(state)
        yield state

After this your expression can be written as:

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)

But the Pythonic way to do it is using a generator function:

def produce(x):
    yield x
    while x != 1:
        x = x / 2 if is_even(x) else 3*x + 1
        yield x
呆萌少年 2024-08-02 09:37:53

劳伦斯提到的黑客行为:

你可以用一个列表理解来完成它,它最终会变成可怕的Python。 无法读取的Python。 可怕的蟒蛇。 我仅出于好奇而提出以下内容,而不是作为实际答案。 不要在您真正想要使用的代码中执行此操作,除非您想体验 python 的内部工作原理。

因此,有 3 种方法:


帮助列表 1

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

result:

[None, None, None, None, None, None, None]
[10, 5, 16, 8, 4, 2, 1]

Helping List 2

2:使用帮助列表,但结果是列表理解的输出。 这主要依赖于 list.append(...) 返回 Nonenot None 评估为 True 和 <出于算术目的,code>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 可爱又美好。 所以你不可能读过这篇文章,因为这种东西不可能存在。 好好。

The hackery referred to by Laurence:

You can do it in one list comprehension, it just ends up being AWFUL python. Unreadable python. Terrible python. I only present the following as a curiosity, not as an actual answer. Don't do this in code you actually want to use, only if you fancy having a play with the inner workings on python.

So, 3 approaches:


Helping List 1

1: Using a helping list, answer ends up in the helping list. This appends values to the list being iterated over until you've reached the value you want to stop at.

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

result:

[None, None, None, None, None, None, None]
[10, 5, 16, 8, 4, 2, 1]

Helping List 2

2: Using a helping list, but with the result being the output of the list comprehension. This mostly relies on list.append(...) returning None, not None evaluating as True and True being considered 1 for the purposes of arithmetic. Sigh.

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]

result:

[10, 5, 16, 8, 4, 2, 1]

Referencing the List Comprehension from within

3: Not using a helping list, but referring back to the list comprehension as it's being built. This is a bit fragile, and probably wont work in all environments. If it doesn't work, try running the code on its own:

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]']))]

result:

[10, 5, 16, 8, 4, 2, 1]

So, now forget that you read this. This is dark, dark and dingy python. Evil python. And we all know python isn't evil. Python is lovely and nice. So you can't have read this, because this sort of thing can't exist. Good good.

念﹏祤嫣 2024-08-02 09:37:53

正如 Kiv 所说,列表理解需要一个已知的序列来迭代。

话虽如此,如果您有一个序列并且专注于使用列表理解,您的解决方案可能会包含如下内容:

[not (x % 2) and (x / 2) or (3 * x + 1) for x in sequence]

Mike Cooper 的答案是一个更好的解决方案,因为它都保留了 x != 1终止,并且这一行读起来不清晰。

As Kiv said, a list comprehension requires a known sequence to iterate over.

Having said that, if you had a sequence and were fixated on using a list comprehension, your solution would probably include something like this:

[not (x % 2) and (x / 2) or (3 * x + 1) for x in sequence]

Mike Cooper's answer is a better solution because it both retains the x != 1 termination, and this line doesn't read cleanly.

忘你却要生生世世 2024-08-02 09:37:53
1

我发现了一个真正奇妙的证明,这个边距太窄而无法容纳。 ——费马

不过,严肃地说,我不相信你可以用 Python 列表推导式来做到这一点。 它们与地图和过滤器具有基本相同的功能,因此您无法在不诉诸黑客手段的情况下突破或查看以前的值。

1

I have discovered a truly marvelous proof of this, which this margin is too narrow to contain. -- Fermat

In all seriousness though, I don't believe you can do this with Python list comprehensions. They have basically the same power as map and filter, so you can't break out or look at previous values without resorting to hackery.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文