0

ネストされたリストのリストに対してリスト インデックスを取得する方法を見つけるのに苦労しています。

たとえば、次の 2 つの関数を使用して、ノードの数、または特定のノードのリストの構造を調べることができます。

t = ['add', [ \
        ['divide a', [ \
            ['if statement', ['Var 9', 'Var 5', 'Var 1', 'Var 4']], \
            ['subtract', [ \
                ['add', [ \
                    ['round to integer', ['Var 10']], 'Var 4'] \
                ], 'Var 9' \
            ]] \
        ]], 'Var 4' \
     ]]

def total_nodes(structure,num_nodes):
    s = structure
    print "N:" , num_nodes , s
    num_nodes += 1
    if isinstance(s,str): return num_nodes    
    if s[1]:
        for x in range(len(s[1])):
            num_nodes = total_nodes(s[1][x], num_nodes)
        return num_nodes 


def get_structure_for_node(structure,counter,find_node=1):
    s = structure
    if not isinstance(counter,int):
        return counter
    if counter == find_node:
        return s
    counter += 1
    if isinstance(s,str): return counter
    if s[1]:
        for x in range(len(s[1])):
            counter = get_structure_for_node(s[1][x],counter,find_node=find_node)
        return counter



print 
print total_nodes(t,0)
print
print get_structure_for_node(t,0,find_node=12)

出力:

N: 0 ['add', [['divide a', [['if statement', ['Var 9', 'Var 5', 'Var 1', 'Var 4']], ['subtract', [['add', [['round to integer', ['Var 10']], 'Var 4']], 'Var 9']]]], 'Var 4']]
N: 1 ['divide a', [['if statement', ['Var 9', 'Var 5', 'Var 1', 'Var 4']], ['subtract', [['add', [['round to integer', ['Var 10']], 'Var 4']], 'Var 9']]]]
N: 2 ['if statement', ['Var 9', 'Var 5', 'Var 1', 'Var 4']]
N: 3 Var 9
N: 4 Var 5
N: 5 Var 1
N: 6 Var 4
N: 7 ['subtract', [['add', [['round to integer', ['Var 10']], 'Var 4']], 'Var 9']]
N: 8 ['add', [['round to integer', ['Var 10']], 'Var 4']]
N: 9 ['round to integer', ['Var 10']]
N: 10 Var 10
N: 11 Var 4
N: 12 Var 9
N: 13 Var 4
14

Var 9

出力から、t から検索したノード '12' へのパスは次のようになります。

t[1][0][1][1][1][1]

しかし、再帰関数を使用しているため、このインデックス キーを追跡する方法を見つけることができませんでした。リスト/ツリーの要素を変更するために必要なもの

テイカーはいますか?

再帰に変数を追加して追跡しようとしていたことを追加する必要があります。これにより、移動先の文字列が構築されます。

パス = "10112101"

その後、後でこれを使用しようとしましたが、正確にすることができず、よりクリーンな方法を好むでしょう。

4

2 に答える 2

3

最も単純な平坦化アルゴリズムは次のとおりです。

def flat_list(l):
    for node in l:
        if isinstance(node, list):
            for i in flat_list(node):
                yield i
        else:
            yield node

フラット化アルゴリズムを変更して追跡するのは簡単です。

def flat_list_keeping_track(l, track=None):
    track = track or ()
    for i, node in enumerate(l):
        new_track = track + (i,)
        if isinstance(node, list):
            for result in flat_list_keeping_track(node, track=new_track):
                yield result
        else:
            yield node, new_track

そして今、あなたはタイプすることができます

def get_structure_for_node(structure, find_node=1):
    return list(flat_list(structure))[find_node][1]

これは最速の方法ではありません。構造が大きく、比較的小さい 'find_node' 値を使用する場合は、そのようなものを記述する必要があります ( get-the-nth-item-of-a-generator-in-python に基づいて):

import itertools
def get_structure_for_node(structure, find_node=1):
    return next(itertools.islice(flat_list(structure), find_node, find_node+1))[1]

速度が本当に重要な場合は、他のフラット化関数を変更することもできます (make -a-flat-list-out-of-list-of-lists-in-pythonまたはMaking-a-flat-list-out-of-a を参照)。 -multi-type-nested-list )。

于 2012-10-12T14:41:05.543 に答える
1

パスを維持するというあなたのアプローチはうまくいくでしょう。

ただし、特定の問題については、ジェネレーターを使用してコードを書き直す方が便利 (かつ Pythonic) かもしれません。

これが意味することは、関数内でインデックスを管理し、関数の実行中にyield部分的な結果を管理することです。

treewalk(node):
    for n in node.children:
        for result in treewalk(n):
            yield result
    else:
        yield node 
于 2012-10-12T14:26:12.640 に答える