有没有什么方法可以转换这个for循环与列表理解?

Boa*_*Boa 1 python for-loop list-comprehension python-2.7

我问的原因是在合并各种数据结构,字典,列表,字符串.

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
Run Code Online (Sandbox Code Playgroud)

我是列表理解的新手,所以如果有可能我真的可以使用解释.干杯.

Mar*_*ers 8

循环当前取决于能够分配bffer.因为赋值是一个语句,而列表推导只能包含表达式,所以将它转换为列表解析需要很多难以理解的可变对象技巧.

因此,将其转换为列表理解将导致无法读取的混乱,没有任何明显的好处(移除list.append()调用的任何速度优势将被可变对象操作抵消).


PM *_*ing 6

为了让您了解为什么尝试将LZW压缩器的循环填充到列表理解中是一个非常糟糕的主意,我实际上已经开始编写一些疯狂的代码来实现这一点.

它使用了一些相当狡猾的技巧,它不适用于Python 3,因为在Python 3中,列表理解在其自己的范围内运行; 在Python 2中,列表理解在周围代码的范围内运行.这意味着我将原始缓冲区传递给list 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))
Run Code Online (Sandbox Code Playgroud)

产量

[116, 104, 105, 115, 32, 100, 97, 116, 97, 32, 130, 32, 128, 138, 133]
22 -> 15
Run Code Online (Sandbox Code Playgroud)

我们实际上并不需要将代码簿的大小保存在单独的变量中.像所有Python的内置容器类型一样,dict会跟踪它的大小,我们可以使用该len()函数来获取它.所以我们可以替换这两行:

codebook[newbuff] = dict_size
dict_size += 1
Run Code Online (Sandbox Code Playgroud)

用这一行:

codebook[newbuff] = len(codebook)
Run Code Online (Sandbox Code Playgroud)

现在这是使用列表理解的疯狂版本.记住小孩, 不要在家里试试!:)

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]
Run Code Online (Sandbox Code Playgroud)

请注意,此版本不仅比我发布的第一个版本难以阅读,而且效率也较低.正如我在开始时所说的那样,它不那么便携,而且它使用了一些完全狡猾的技巧,这些技巧永远不会用在严肃的代码中.

列表理解很酷,一旦你习惯了它们,它们可以使你的代码更简洁,这有助于提高可读性,只要你不试图在它们中做太多.列表comp 比在"传统"样式循环中使用的等效代码稍微有效,但它们不是魔术,并且使用难以理解的列表理解而不是一个清晰可读的传统循环不是 Pythonic..appendforfor