3

これは私の以前の質問に関連しています:ネストされたリストから区切り文字列への変換

区切り文字列形式でデータを送信する外部サービスがあります。これは、最大 3 レベルの深さのアイテムのリストです。レベル 1 は「|」で区切られます。レベル 2 は「;」で区切られます。レベル 3 は「,」で区切られます。各レベルまたは要素には、0 個以上のアイテムを含めることができます。簡単な例は次のとおりです。
a,b;c,d|e||f,g|h;;

これをネストされたリストに変換する関数があります。これは Python での操作方法です。

def dyn_to_lists(dyn):  
    return [[[c for c in b.split(',')] for b in a.split(';')] for a in dyn.split('|')]

上記の例では、この関数の結果は次のようになります。

>>> dyn = "a,b;c,d|e||f,g|h;;"
>>> print (dyn_to_lists(dyn))
[[['a', 'b'], ['c', 'd']], [['e']], [['']], [['f', 'g']], [['h'], [''], ['']]]

リストの場合、任意のレベルでアイテムが 1 つしかない場合は、1 アイテム リストではなくスカラーとして使用します。空のリストについては、単なる空の文字列として扱います。私はこの機能を思いつきました。これはうまくいきます:

def dyn_to_min_lists(dyn):
    def compress(x): 
        return "" if len(x) == 0 else x if len(x) != 1 else x[0]

    return compress([compress([compress([item for item in mv.split(',')]) for mv in attr.split(';')]) for attr in dyn.split('|')])

この関数を使用し、上記の例を使用すると、返されます ( *下記の更新を参照):

[[['a', 'b'], ['c', 'd']], 'e', '', ['f', 'g'], ['h', '', '']]

Python は初めてなので、これが最善の方法であるとは確信していません。これを処理するためのよりクリーンな方法はありますか?

これにより、大量のデータが通過する可能性があります。これを達成するためのより効率的/スケーラブルな方法はありますか?

アップデート

元の圧縮機能にバグが見つかりました。内側のリストに複数のアイテムがある場合、外側のリストは削除できません。これにより、変換が元に戻せなくなります。このために、@Blender の圧縮関数を次のように更新しました。

def __compress(x): 
    if len(x) > 1:
        return x
    elif not x:
        return ''
    else:
        if type(x[0]) != list:
            return x[0]
        else:
            return x

これで、次の正しい出力が返されます。

[[['a', 'b'], ['c', 'd']], 'e', '', [['f', 'g']], ['h', '', '']]
4

1 に答える 1

1

速度を上げるためにいくつかのことを行うことができます。

  • 最も内側のリスト内包表記を取り除きます:[item for item in mv.split(',')]になりmv.split(',')ます。無駄だ。
  • compress関数を関数の外に移動しdyn_to_min_listsます。を実行するたびに作成する必要はありませんdyn_to_min_lists
  • 真実性を使用すると、を呼び出すよりも高速lenになるため、 に置き換えます。len(x) == 0not x
  • 関数の条件を並べ替えcompressて、より一般的なケースが最初に現れるようにすると、速度も向上します。

したがって、結果のコードは次のとおりです。

def compress(x): 
    if len(x) > 1:
        return x
    elif not x:
        return ''
    else:
        return x[0]

def parse(s):
    return compress([
        compress([
            compress(b.split(',')) for b in a.split(';')
        ]) for a in s.split('|')
    ])

速度比較は次のとおりです。

>>> %timeit parse('a,b;c,d|e||f,g|h;;')
100000 loops, best of 3: 10 µs per loop
>>> %timeit dyn_to_min_lists('a,b;c,d|e||f,g|h;;')
10000 loops, best of 3: 15.6 µs per loop

私のコンピューターでは約 36% 高速です。これがスクリプトの非常に重要な部分である場合は、C で実装し、C 拡張機能にコンパイルします。

于 2013-10-27T04:48:32.180 に答える