3

データ構造のトラバーサルを表す文字列のリストがあります。リンク リストのトラバーサルをよりコンパクトな表現にまとめたいと考えています。nextこれを行うには、隣接リンクとリンクの数を数えて、prevそれらを 1 つの整数にまとめたいと思います。

私がやりたい変換の例を次に示します。

['modules']                                   -->  ['modules']
['modules', 'next']                           -->  ['modules', 1]
['modules', 'prev']                           -->  ['modules', -1]
['modules', 'next', 'next', 'next', 'txt']    -->  ['modules', 3, 'txt']
['modules', 'next', 'prev', 'next', 'txt']    -->  ['modules', 1, 'txt']
['super_blocks', 'next', 's_inodes', 'next']  -->  ['super_blocks', 1, 's_inodes', 1]

nextリンクは +1 としてカウントされ、各リンクprevは -1 としてカウントされます。隣接するnextprevは互いに打ち消し合います。それらは任意の順序で来る可能性があります。

これに対する実用的な解決策がありますが、満足のいくエレガントで Pythonic な解決策を見つけるのに苦労しています。

4

4 に答える 4

6

ジェネレーターを使用できます:

def links(seq):
    it = iter(seq)
    while True:
        el = next(it)
        cnt = 0
        try:
            while el in ['prev', 'next']:
                cnt += (1 if el == 'next' else -1)
                el = next(it)
        finally:
            if cnt != 0:
                yield cnt
        yield el

print list(links(['modules', 'next', 'prev', 'next', 'txt']))

同数のnextとを含むシーケンスprevは完全に削除されることに注意してください。コードを変更して、それが必要な場合は簡単に生成0できます(これについては、要件が少し不明確だと思います)。

于 2013-03-21T21:49:40.050 に答える
1

これが頭に浮かんだ最も簡単なアプローチです。率直であることは、理解、デバッグ、および将来のメンテナンスにとって貴重な品質です。

def process(l):
    result = []
    count = 0
    keepCount = False
    for s in l:
        if s == "next":
            count += 1
            keepCount = True
        elif s == "prev":
            count -= 1
            keepCount = True
        else:
            if keepCount:
                result.append(count)
                count = 0
                keepCount = False
            result.append(s)
        # end if
    # end for
    if keepCount:
        result.append(count)

    return result
# end process()

ただし、NPE のジェネレーターの使用の方が好きです。(私のものは、'result.append()' を 'yield' に変更することで簡単に変換できます) 彼の(元の)答えは私のものとほぼ同じですが、次/前のトークンが隣接している場合に備えて 0 カウントを含めます。等しい数で。

于 2013-03-21T21:54:52.383 に答える
1

どうですか:

def convert(ls):
    last = None
    for x in ls:
        if x == 'prev': x = -1
        if x == 'next': x = +1
        if isinstance(x, int) and isinstance(last, int):
            x += last
        elif last:  # last is not None if you want zeroes
            yield last
        last = x
    yield last
于 2013-03-21T22:15:12.460 に答える
1

少しはreduce()どうですか?

def collapse(lst):
    was_link = [False] # No nonlocal in Python 2.x :(
    def step(lst, item):
        val = { 'prev': -1, 'next': 1 }.get(item)

        if was_link[0] and val:
            lst[-1] += val
        else:
            lst.append(val or item)
        was_link[0] = bool(val)

        return lst

    return reduce(step, [[]] + lst)
于 2013-03-21T22:12:00.900 に答える