是否有可能在Python中定义递归列表理解?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中定义递归列表理解?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
工作(对于非嵌套listcomp)...这就是为什么我澄清没有合格证明我的说法,稳定,稳定访问“正在建立的列表”的方法 - 特殊的,未公开的“名称”'_[1]'
(故意选择不成为有效的标识符;-)是“实现工件”的顶点和任何依赖它的代码应该摆脱它的苦难;-)。
设置的操作使它成为O(n log(n)),我很确定。 – 2010-04-14 16:30:26
@ Python中的dash-tom-bang集合并不像红黑树那样实现(就像在STL中一样),但是据我所知,它使用散列,所以它将是O(N)。 – 2010-04-14 18:38:13
@Justin是正确的 - python集合和字典是非常优化的散列,其中O(1)分摊成本用于添加项目,O(1)成本用于查找。 – 2010-04-15 00:38:18
没有。它将不起作用,在列表理解正在执行时没有self
的引用。
而主要原因当然是列表解析不是为这个用途而设计的。
不知道这是否是你想要的,但你可以写嵌套列表理解:
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)
注意,在NUMS项目需要哈希的。
您还可以执行以下操作。这是一个接近,因为我可以达到你的原始想法。但是这并不像创建set
那样有效。
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)'返回一个列表。 – 2010-04-15 09:19:28
@PreludeAndFugue:好点。我会改变代码。 – hughdbrown 2010-04-15 21:51:01
其实你可以!这个例子有一个解释,希望能说明如何。
定义递归的例子,只有当它是5或更多时才得到一个数字,如果不是,递增它并再次调用'check'函数。重复这个过程,直到它在这一点回报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, 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 '相同'的功能,除了在一个或两个添加一个子句,其中的参数被修改,以便达到终端条件,然后以这种方式去g(x,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]
>>>
克隆lambda是不必要的;你可以使用通用代理作为第一个lambda来允许任何第二个lambda自己调用。 '(lambda f,arg:f(f,arg))(lambda self,v:....,firstvalue)' – 2014-11-03 19:20:40
如果订单不是问题,则使用list(set(num))'。否则,请查看http://docs.python.org/library/itertools.html中的'unique_everseen'。 – kennytm 2010-04-14 15:05:48
泄漏抽象警报。理解不应该被认为是循环,在我看来,即使它们可能在cpython中被实现为循环.. – wim 2013-04-16 03:49:46