2

私が書いているPythonプログラムでは、各ノードを後続ノードにマップするディクショナリを使用してリンクリストを作成しました(最後のノードはNoneにマップされています)。

(実際、辞書には、ウィキペディアがスパゲッティスタックと呼ばれるものが含まれています。これは、各ノードがその親にリンクされているが、その子にはリンクされていないツリーです。これは、リーフノードからルートノードへの部分的に重複するパスが多数あることを意味します。 。私は、特定のリーフノードから始まるこれらのパスの1つだけを気にします。これは、辞書内のすべての要素を反復処理することを含むソリューションを除外することを除いて、質問にとって実際には重要ではありません。)

このリストを反復可能として別の関数に渡す必要があります。ジェネレーター関数(以下のコードを参照)を使用してこれを実行できることは知っていますが、必要なイテレーターを1行(またはジェネレーター式)で作成するための組み込み関数が必要なようです。ドキュメントを少し検索しましたが、itertoolsまたはfunctoolsモジュールには何も当てはまらないようで、他にどこを見ればよいかわかりません。

これが私が今持っているジェネレーター関数です。外側の関数は削除(インライン化)できますが、内側のジェネレーターは、データを反復可能にする唯一の簡単な方法のようです。

def makeListGenerator(nextDict, start):
    def gen(node):
        while node:
            yield node
            node = nextDict[node]
    return gen(start)

この種のジェネレーターにはパターンがあるはずですが、それが何と呼ばれるかはわかりません。一般的なバージョンは次のとおりです。

def makeGenericGenerator(nextFunc, continueFunc, start):
    def gen(value):
         while continueFunc(value):
             yield value
             value = nextFunc(value)
    return gen(start)

次の呼び出しを使用して、これを使用して特定のバージョンを実装できます。

makeGenericGenerator(lambda v: nextDict[v], bool, start)

そのようなものはPython標準ライブラリにすでに存在しますか?

4

2 に答える 2

7

あなたが直面する本質的な問題は、イテラブルから別の値が取得されるたびに、イテラブルがその値を記憶しなければならないことです。これにより、次の値を生成する方法がわかります。つまり、iterableは独自の状態を維持する必要があります。

つまり、あなたの質問に対する良い答えがあるかどうかにかかわらず、ジェネレーターを使用することはおそらく正しい解決策です-それはまさにジェネレーターが作られた目的だからです!ジェネレーターの要点は、nextメソッドの呼び出しの間に状態を保存することです。これがまさに必要なことです。

一方、ジェネレータ式は、ステートレス変換に適しています。多くの人が彼らに靴べらの状態をしようとします、そしてそれは一般的にちょっと醜いです。私は実際にあなたのケースのためにそれをしようとして少し時間を費やしました、そしてジェネレータ式を機能させることができませんでした。やっとそのような作品を見つけました。これは、あまり知られていないcallable_iteratorバージョンのiter:を使用します。

>>> d = {1:2, 2:3, 3:4, 4:5, 5:None}
>>> list(iter(lambda st=[1]: st.__setitem__(0, d[st[0]]) or st[0], None))
[2, 3, 4, 5]

私はこれを答えとしてではなく、なぜこれがうまく機能しないのかを示すものとして提示します。

于 2012-06-02T22:28:07.577 に答える
2
nodes = {
    'A':'B',
    'B':'C',
    'C':'D',
    'D':None
}

print (lambda f: lambda g: f(f,g)) (lambda f,x: [x] + f(f, nodes[x]) if x else [])('A')
# ['A', 'B', 'C', 'D']
于 2012-06-02T22:55:30.127 に答える