Python 中的递归列表理解?

发布于 2024-08-29 01:29:05 字数 222 浏览 4 评论 0原文

是否可以在 Python 中定义递归列表理解?

可能是一个简单的例子,但大致意思是:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
willThisWork = [x for x in nums if x not in self] # self being the current comprehension

这样的事情可能吗?

Is it possible to define a recursive list comprehension in Python?

Possibly a simplistic example, but something along the lines of:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
willThisWork = [x for x in nums if x not in self] # self being the current comprehension

Is anything like this possible?

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

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

发布评论

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

评论(7

只等公子 2024-09-05 01:29:05

不,没有(有记录的、可靠的、稳定的……;-)方法来引用“当前的理解”。您可以只使用循环:

res = []
for x in nums:
  if x not in res:
    res.append(x)

当然,这是非常昂贵的(O(N 平方)),因此您可以使用辅助 set 对其进行优化(我假设保持 < code>res 与 nums 中的项目一致,否则 set(nums) 就可以了;-)...:

res = []
aux = set()
for x in nums:
  if x not in aux:
    res.append(x)
    aux.add(x)

这对于非常长的列表(O(N) 而不是 N 平方)。

编辑:在 Python 2.5 或 2.6 中,vars()['_[1]'] 实际上可能适用于您想要的 self 角色(对于非嵌套列表)...这就是为什么我通过澄清没有记录的、可靠的、稳定的方式来访问“正在建立的列表”来限定我的陈述——那种特殊的、未记录的“name”'_[1]'(故意选择不作为有效标识符;-)是“实现工件”的顶峰,任何依赖它的代码都应该摆脱它的痛苦;-)。

No, there's no (documented, solid, stable, ...;-) way to refer to "the current comprehension". You could just use a loop:

res = []
for x in nums:
  if x not in res:
    res.append(x)

of course this is very costly (O(N squared)), so you can optimize it with an auxiliary set (I'm assuming that keeping the order of items in res congruent to that of the items in nums, otherwise set(nums) would do you;-)...:

res = []
aux = set()
for x in nums:
  if x not in aux:
    res.append(x)
    aux.add(x)

this is enormously faster for very long lists (O(N) instead of N squared).

Edit: in Python 2.5 or 2.6, vars()['_[1]'] might actually work in the role you want for self (for a non-nested listcomp)... which is why I qualified my statement by clarifying there's no documented, solid, stable way to access "the list being built up" -- that peculiar, undocumented "name" '_[1]' (deliberately chosen not to be a valid identifier;-) is the apex of "implementation artifacts" and any code relying on it deserves to be put out of its misery;-).

梦醒时光 2024-09-05 01:29:05

Python 3.8开始,并引入了赋值表达式(PEP ):= 运算符),它提供了命名表达式结果的可能性,我们可以通过更新列表理解中的变量来引用已经看到的项目

# items = [1, 1, 2, 2, 3, 3, 4, 4]
acc = []; [acc := acc + [x] for x in items if x not in acc]
# acc = [1, 2, 3, 4]

  • 572 list acc 表示已见过的元素的运行列表。
  • 对于每个项目,这会检查它是否已经是 acc 列表的一部分;如果没有:
    • 通过赋值表达式将项目附加到acc (acc := acc + [x])
    • 同时使用 acc 的新值作为此项的映射值

Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), which gives the possibility to name the result of an expression, we could reference items already seen by updating a variable within the list comprehension:

# items = [1, 1, 2, 2, 3, 3, 4, 4]
acc = []; [acc := acc + [x] for x in items if x not in acc]
# acc = [1, 2, 3, 4]

This:

  • Initializes a list acc which symbolizes the running list of elements already seen
  • For each item, this checks if it's already part of the acc list; and if not:
    • appends the item to acc (acc := acc + [x]) via an assignment expression
    • and at the same time uses the new value of acc as the mapped value for this item
忆伤 2024-09-05 01:29:05

其实你可以!这个带有解释的示例希望能够说明如何进行。

定义递归示例,仅当数字等于或大于 5 时才获取数字,如果不是,则递增该数字并再次调用“检查”函数。重复此过程,直到达到 5,此时返回 5。

print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ]

结果:

[5, 5, 5, 5, 5, 6]
>>> 

本质上,两个匿名函数以这种方式交互:

let f(g,x) = {  
                 expression, terminal condition
                 g(g,x), non-terminal condition
             }

let g(f,x) = {  
                 expression, terminal condition
                 f(f,x), non-terminal condition
             }

使 g,f 成为“相同”函数,除了在其中一个或两个中添加一个子句,其中参数被修改,以便导致达到终止条件,然后继续
f(g,x) 这样 g 就成为 f 的副本,使其类似于:

f(g,x) = {  
                 expression, terminal condition
                 {
                    expression, terminal condition,
                    g(g,x), non-terminal codition
                 }, non-terminal condition
             }

您需要这样做,因为在执行时您无法访问匿名函数本身。

(lambda f,v: somehow call the function again inside itself )(_,_)

在这个例子中让 A = 第一个函数,B 作为第二个函数。我们将 A 传递给 B 作为 f,i 作为 v。现在,B 本质上是 A 的副本,并且它是已传递的参数,您现在可以调用 B,这就像调用 A 一样。

这会在列表中生成阶乘

print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ]

[1, 2, 6, 120, 720, 5040]
>>> 

Actually you can! This example with an explanation hopefully will illustrate how.

define recursive example to get a number only when it is 5 or more and if it isn't, increment it and call the 'check' function again. Repeat this process until it reaches 5 at which point return 5.

print [ (lambda f,v: v >= 5 and v or f(f,v+1))(lambda g,i: i >= 5 and i or g(g,i+1),i) for i in [1,2,3,4,5,6] ]

result:

[5, 5, 5, 5, 5, 6]
>>> 

essentially the two anonymous functions interact in this way:

let f(g,x) = {  
                 expression, terminal condition
                 g(g,x), non-terminal condition
             }

let g(f,x) = {  
                 expression, terminal condition
                 f(f,x), non-terminal condition
             }

make g,f the 'same' function except that in one or both add a clause where the parameter is modified so as to cause the terminal condition to be reached and then go
f(g,x) in this way g becomes a copy of f making it like:

f(g,x) = {  
                 expression, terminal condition
                 {
                    expression, terminal condition,
                    g(g,x), non-terminal codition
                 }, non-terminal condition
             }

You need to do this because you can't access the the anonymous function itself upon being executed.

i.e

(lambda f,v: somehow call the function again inside itself )(_,_)

so in this example let A = the first function and B the second. We call A passing B as f and i as v. Now as B is essentially a copy of A and it's a parameter that has been passed you can now call B which is like calling A.

This generates the factorials in a list

print [ (lambda f,v: v == 0 and 1 or v*f(f,v-1))(lambda g,i: i == 0 and 1 or i*g(g,i-1),i) for i in [1,2,3,5,6,7] ]

[1, 2, 6, 120, 720, 5040]
>>> 
王权女流氓 2024-09-05 01:29:05

不确定这是否是您想要的,但您可以编写嵌套列表理解:

xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)]
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]]

从您的代码示例中,您似乎只想简单地消除重复项,您可以使用集合来做到这一点:

xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4]))
assert xs == [1, 2, 3, 4]

Not sure if this is what you want, but you can write nested list comprehensions:

xs = [[i for i in range(1,10) if i % j == 0] for j in range(2,5)]
assert xs == [[2, 4, 6, 8], [3, 6, 9], [4, 8]]

From your code example, you seem to want to simply eliminate duplicates, which you can do with sets:

xs = sorted(set([1, 1, 2, 2, 3, 3, 4, 4]))
assert xs == [1, 2, 3, 4]
万人眼中万个我 2024-09-05 01:29:05

不。它不起作用,在执行列表理解时没有 self 可以引用。

当然,主要原因是列表推导式不是为此用途而设计的。

no. it won't work, there is no self to refer to while list comprehension is being executed.

And the main reason of course is that list comprehensions where not designed for this use.

罪歌 2024-09-05 01:29:05

不。

但看起来您正在尝试列出 nums 中的唯一元素。

您可以使用set

unique_items = set(nums)

请注意,nums 中的项目需要是可散列的。

您还可以执行以下操作。这是一个结束,因为我可以得到你最初的想法。但这不如创建集合那么有效。

unique_items = []
for i in nums:
    if i not in unique_items:
        unique_items.append(i)

No.

But it looks like you are trying to make a list of the unique elements in nums.

You could use a set:

unique_items = set(nums)

Note that items in nums need to be hashable.

You can also do the following. Which is a close as I can get to your original idea. But this is not as efficient as creating a set.

unique_items = []
for i in nums:
    if i not in unique_items:
        unique_items.append(i)
烟─花易冷 2024-09-05 01:29:05

这样做:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
set_of_nums = set(nums)
unique_num_list = list(set_of_nums)

或者甚至这样做:

unique_num_list = sorted(set_of_nums)

Do this:

nums = [1, 1, 2, 2, 3, 3, 4, 4]
set_of_nums = set(nums)
unique_num_list = list(set_of_nums)

or even this:

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