2009-06-19 64 views
1

我一直在想一種方法來使用列表表達式遍歷層次結構,如鏈接列表,但還沒有提出任何看起來工作的東西。如何使用列表理解走出鏈表?

基本上,我想這個代碼轉換:

p = self.parent 
names = [] 
while p: 
    names.append(p.name) 
    p = p.parent 
print ".".join(names) 

成一個班輪,如:

print ".".join([o.name for o in <???>]) 

我不知道該怎麼辦遍歷在???一部分,雖然,以通用方式(如果它甚至可能的話)。我有幾個具有類似.parent類型屬性的結構,並且不希望爲每個結構都寫入yielding函數。

編輯:

我不能使用對象本身的__iter__方法,因爲它已經被用於遍歷包含對象本身的值。除了liori之外,大多數其他答案都是對屬性名稱進行硬編碼,這是我想要避免的。

下面是基於liori的回答我的改編:

import operator 
def walk(attr, start): 
    if callable(attr): 
    getter = attr 
    else: 
    getter = operator.attrgetter(attr) 

    o = getter(start) 
    while o: 
    yield o 
    o = getter(o) 

回答

2

如果您希望您的解決方案是一般情況下,使用一般的己技巧。這是一個固定點狀發生器:

def fixedpoint(f, start, stop): 
    while start != stop: 
     yield start 
     start = f(start) 

它將返回一個發生器產生啓動中,f(開始)中,f(F(開始)),F(F(F(啓動))),..只要這些值都不等於停止。

用法:

print ".".join(x.name for x in fixedpoint(lambda p:p.parent, self, None)) 

我個人助手庫多年來類似的定點樣的功能?它是快速黑客非常有用。

+0

是的!這是我正在尋找的東西。我用我的改編版更新了我的答案。 – 2009-06-20 00:56:49

1

列表理解支持不迭代器(具有next()方法)的對象。你需要爲你的結構定義一個迭代器,以便能夠以這種方式迭代它。

6

我能想到的最接近的事是創建一個父發生器:

# Generate a node's parents, heading towards ancestors 
def gen_parents(node): 
    node = node.parent 
    while node: 
     yield node 
     node = node.parent 

# Now you can do this 
parents = [x.name for x in gen_parents(node)] 
print '.'.join(parents) 
1

你的LinkedList需要可迭代它才能正常工作。

Here's a good resource on it. (PDF warning)它對迭代器和生成器都非常深入。

一旦你這樣做,你就可以只是這樣做:

print ".".join([o.name for o in self]) 
+0

該PDF受限訪問...也許使信息可用? – SumNeuron 2017-03-21 10:06:34