在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
有没有类似这样的可能性?
在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
有没有类似这样的可能性?
不,没有(文档化的、可靠的、稳定的......;-)方法来引用“当前理解”。你可以使用一个循环:
res = []
for x in nums:
if x not in res:
res.append(x)
当然,这非常耗费资源(O(N的平方)),所以您可以使用辅助set
进行优化(我假设保持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
角色(对于非嵌套的列表推导式)中起作用......这就是为什么我限定了我的陈述,并澄清没有文档化,稳定的方法来访问“正在建立的列表” - 那个奇特的、未记录的“名称”'_[1]'
(故意选择不是一个有效的标识符;-)是“实现工件”的顶点,任何依赖它的代码都应该被淘汰。;-)
从 Python 3.8
开始,引入了赋值表达式(PEP 572)(:=
运算符),这使得我们有可能通过更新列表推导式中的变量来引用已经看到的项目:
# 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]
这个函数:
acc
,代表已经被查看过的元素列表acc
列表中;如果不是:
acc
中(acc := acc + [x]
)acc
的新值作为该项的映射值实际上你是可以的!这个例子及其解释应该会很好地说明如何做到。
定义递归例子,只有当数字大于等于5时才获取它,如果不是,则将其增加并再次调用“check”函数。重复此过程直到它达到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为第二个。我们称将B传递给A的过程为f,i作为v。现在由于B本质上是A的一个副本并且它是一个被传递的参数,你可以像调用A一样调用B。
这将生成一个阶乘列表。
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]
>>>
(lambda f,arg: f(f,arg))(lambda self,v: .... , firstvalue)
- Sean Gugler不确定这是否是您想要的,但您可以编写嵌套的列表推导式:
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]
不。
但是看起来你正在尝试制作nums中唯一元素的列表。
你可以使用一个set
:
unique_items = set(nums)
unique_items = []
for i in nums:
if i not in unique_items:
unique_items.append(i)
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)
unique_num_list = list(set_of_nums)
。sorted(set_of_nums)
返回一个列表。 - Gary Kerr不行,因为列表推导式执行时没有 self
可以引用。
当然,主要原因是列表推导式不是为此设计的。
list(set(num))
。否则,请查看 http://docs.python.org/library/itertools.html 中的unique_everseen
。 - kennytm