只是爲了讓你知道爲什麼它是一個確實不好主意嘗試和填充你的LZW壓縮器的循環列表理解,我已經寫了一些瘋狂的代碼,這樣做。
它使用了一些比較狡猾的技巧,它不適用於Python 3,因爲在Python 3中,列表理解運行在它自己的範圍內;在Python 2中,列表理解運行在周圍代碼的範圍內。這意味着我將原始緩衝區傳遞到列表組件中的技巧在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的內置容器類型一樣,字典跟蹤其大小,我們可以使用len()
函數來獲取它。這條線
codebook[newbuff] = dict_size
dict_size += 1
:所以我們可以替換這些2線
codebook[newbuff] = len(codebook)
現在,這裏是一個使用列表理解瘋狂的版本。記住孩子,請不要試試這個在家裏! :)
def lzw_compress_crazy(data):
dict_size = 128
codebook = {chr(i): i for i in range(dict_size)}
def magic(oldbuff, ch):
newbuff = oldbuff + ch
if newbuff in codebook:
return [(newbuff, None)]
else:
codebook[newbuff] = len(codebook)
return [(ch, codebook[oldbuff])]
oldbuff = ""
return [result for ch in data
for oldbuff, result in magic(oldbuff, ch) if result]
請注意,這個版本不僅比我發佈的第一個版本更難讀取,它的效率也不高。正如我在開始時所說的那樣,它的便攜性較差,而且它使用了一些永遠不會用於嚴肅代碼的完全狡猾的技巧。
列表理解是冷靜,一旦你已經習慣了他們,他們可以使你的代碼更簡潔,它可以幫助可讀性,只要你不要試圖做太多在其中。列表比較是略比「傳統」風格for
循環使用.append
等效代碼效率更高,但它們不是魔術,並使用難以理解的列表理解,而不是AA漂亮清晰可讀傳統for
環路不 Python的。
爲什麼需要這個被轉換成一個列表理解?這真的會傷害可讀性。 –
你爲什麼想要?如果由某種惡魔巫術,它是可以堵塞所有到一個列表理解,這將是完全不可讀。 –
'[do_everything_youre_doing_in_the_loop(字符),用於字符串的字符]'...?這是太多的代碼內聯成一個修真... – deceze