2016-11-21 4 views
1

私が求めているのは、さまざまなデータ構造、dict、list、stringを組み込んでいるからです。これをリストの解説付きループに変換する方法はありますか?

bffer = "" 
dict_size = 128 
for character in string: 
    appnd_bffer = bffer + character 
    if appnd_bffer in codebook: 
     bffer = appnd_bffer 
    else: 
     output_list.append(codebook[bffer]) 
     codebook[appnd_bffer] = dict_size 
     dict_size += 1 
     bffer = character 

私は可能な場合は説明を使用することができますので、私はリストの補完に新しいです。乾杯。

+8

なぜこれをリストの理解に変換する必要がありますか?それは本当に読みやすさを傷つけるでしょう。 –

+0

なぜあなたはしたいですか?何らかの悪魔的なブードーによって、すべてのことをリスト内包にすることができれば、それは全く読めないでしょう。 –

+0

'[do_everything_youre_doing_in_the_loop(文字列)の文字列]' ...?これは理解するためにあまりにも多くのコードです... – deceze

答えて

6

なぜ実際にのLZWコンプレッサーのループをリストの理解に詰め込んでもらうのが悪い考えを伝えるために、私は実際に先に進み、ちょうどそれを行う狂ったコードを書いています。

Python 3ではリスト内包が独自のスコープで実行されるため、かなり面倒なトリックが使用され、Python 3では機能しません。 Python 2では、リスト内包は周囲のコードの範囲で実行されます。これは、元のバッファをリストcompに渡すという私のやり方がPython 3ではうまくいかないことを意味します。

まず、元のコードを関数にラップし、いくつかの変数名を変更します。それを実行可能でテスト可能な例にするためのエキストラ。

from __future__ import print_function 

def lzw_compress_Boa(data): 
    dict_size = 128 
    codebook = {chr(i): i for i in range(dict_size)} 

    output_list = [] 
    oldbuff = "" 
    for ch in data: 
     newbuff = oldbuff + ch 
     if newbuff in codebook: 
      oldbuff = newbuff 
     else: 
      output_list.append(codebook[oldbuff]) 
      codebook[newbuff] = dict_size 
      dict_size += 1 
      oldbuff = ch 
    return output_list 

data = 'this data is this data' 

output_list = lzw_compress_Boa(data) 
print(output_list) 
print(len(data), '->', len(output_list)) 

出力

[116, 104, 105, 115, 32, 100, 97, 116, 97, 32, 130, 32, 128, 138, 133] 
22 -> 15 

私たちが実際に別の変数に、コードブックのサイズを維持する必要はありません。 Pythonに組み込まれているすべてのコンテナ型と同様に、dictはそのサイズを追跡しており、len()関数を使用してそれを取得できます。このラインで

codebook[newbuff] = dict_size 
dict_size += 1 

:だから私たちは、これらの2行を置き換えることができ

codebook[newbuff] = len(codebook) 

は今ここにリストの内包を使用してクレイジーバージョンです。子供を覚えて、してください家でこれを試してみてください! :)

このバージョンは、私が投稿した最初のものより読むのが難しいだけでなく、効率も悪いことに注意してください。私が最初に言ったように、移植性が低く、深刻なコードでは決して使用しないでください。

リスト内包はすばらしく、使い慣れたらコードを簡潔にすることができます。コードをあまり使わない限り、読みやすくすることができます。リストCOMPは「伝統的」なスタイルで.appendforループを使用して同等のコードよりも少しより効率的ですが、彼らは魔法ではありません、代わりにAA素敵な明確な読みやすい伝統的なforループの不可解なリストの内包表記を使用すると、ない Python的です。

+0

レイジー。私は 'Popen(['working_c_implementation']、stdin = PIPE、stdout = PIPE)のbを見たいと思っています。 –

+0

@ZeroPiraeus LOL。私は反復可能なクラスで状態を維持しようとしていましたが、あまりにも狂っていないと決めました。 :) –

2

いいえ、リストを構成する式以外の式が含まれているため(例:dict_size += 1)、これをリストの理解にすることはできません。これらの表現は、リストの理解に入る場所がありません。理解の唯一の目的は、そのオブジェクトを作成することだけです。ループの1回の反復のロジックを含む別の関数を作成し、ループ内でその関数を使用するのに役立つものは何でしょうか。

+1

それでもやり遂げることができます。しかし、それは読むことができません。 'dict_size'の値は' itertools.count() 'オブジェクトで扱うことができます。 –

+0

ありがとうございました。簡単な質問ですが、関数を追加してコードに肯定的な変化があったとしたらどうでしょうか?読みやすさ/「清潔さ」の点でどちらですか? – Boa

+0

@Boa通常は良い習慣ですが、一般的にあなたの状況に依存します – Noah

8

ループは現在、bfferに割り当てることができるかどうかによって異なります。代入はステートメントであり、リスト内包語にはしか含まれていないため、これをリスト内包表記に変換するには、変更可能なオブジェクトで多くの難しそうなトリッキーが必要です。

このように、これをリストの理解に変換すると、明確なメリットはありませんが、解読不能になります(list.append()呼び出しを削除することによる速度のメリットは、変更可能なオブジェクトの操作によって相殺されます)。

+1

誰かが*不可解な*についての明らかな言葉遣いをまだしていないのですか? – deceze

+1

@deceze:私はそれを避けようとしていました! :-D –

+0

私は包括的な例を見ることができる方法はありますか?私はこれが可能だとは思わなかった – Noah

関連する問題