【问题标题】:Run Length Encoding the code [closed]运行长度编码代码[关闭]
【发布时间】:2018-08-26 22:20:39
【问题描述】:

我对编码非常陌生,因此选择 python 作为我的第一门编码语言。我正在做一个名为 Run Length Encoding 的练习。经过一番搜索,我找到了解决方案,但我很难理解代码。有人可以破解此代码并用简单的语言进行解释。谢谢。

string = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'
x=''.join(['{}{}'.format(k, sum(1 for _ in g)) for k, g in groupby(string)])

【问题讨论】:

  • 您是否 (a) 没有阅读 groupby 的文档,(b) 阅读但不理解它们,或者 (c) 理解它们但不明白如何分解其余部分?在每种情况下,答案所关注的内容会有所不同。
  • 您的代码不完整。 groupby 不是标准函数。它必须从包中导入;确切的行为将取决于它是从哪个包导入的。
  • @AJNeufeld 我认为很明显他在这里使用了itertools.groupby。虽然如果他把这个问题说清楚会更好,但我认为这不是无法回答的。
  • @abarnert 我确实阅读了 groupby 的文档。我只是不明白这一行发生了什么。 Join 中有“for”函数。我只是无法理解这段代码。

标签: python python-3.x run-length-encoding


【解决方案1】:

首先要做的是将表达式分解成更小的表达式:

bits = ['{}{}'.format(k, sum(1 for _ in g)) for k, g in groupby(string)]
x=''.join(bits)

第二个很简单:我们有一些位列表,每个位都是一个字符串,我们只需将它们连接成一个大字符串。

第一个是列表推导。每个列表理解都可以重写为围绕appendfor 语句,所以让我们这样做:

bits = []
for k, g in groupby(string):
    bits.append('{}{}'.format(k, sum(1 for _ in g)))

如果您以前从未见过groupbygroupby 部分可能看起来很棘手,但如果您只是单独调用它,那应该很明显:

for k, g in groupby(string):
    print(k, list(g))

这给了你:

W ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W']
B ['B']
W ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W']
B ['B', 'B', 'B']
W ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W']
B ['B']

换句话说,每个组 g 是一组相等的元素,而 k 正是它们都相等的东西。


现在让我们分解内部语句:

bits.append('{}{}'.format(k, sum(1 for _ in g)))

分成几部分:

count = sum(1 for _ in g)
bit = '{}{}'.format(k, count)
bits.append(bit)

最后两行希望是显而易见的。所以,我们只剩下第一个了。


我们在生成器表达式上调用sum。生成器表达式就像列表推导式一样,但是是惰性的,我们不关心这里的惰性,所以我们可以像上面一样分解它:

things = []
for _ in g:
    things.append(1)
count = sum(things)

所以现在应该很明显sum(1 for _ in g) 做了什么:这只是g 中的事物数量。实际上,它就像调用 len(g) 一样,只是它适用于任意可迭代对象,包括惰性迭代器,而不仅仅是序列。

这是计算可能延迟迭代的惯用方法——但我们可以将其替换为(以牺牲一点性能为代价):

count = len(list(g))

所以,把它们重新组合起来:

  • 使用groupby 将字符串转换为一组组,每组都是同一个字符反复重复。
  • 对于每一个:
    • 计算该组的长度。
    • 使用键 'W'Ws 组有 12 个成员这一事实创建一个类似 'W12' 的字符串。
    • 将其附加到列表中。
  • 获取['W12', 'B1', 'W12', 'B3', 'W24', 'B1'] 的列表并将其加入字符串'W12B1W12B3W24B1'

【讨论】:

    【解决方案2】:

    考虑s = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB'
    您的代码相当于:

    x=''.join(['{}{}'.format(k, len(list(g))) for k, g in groupby(s)])
    

    x=''.join([str(k) + str(len(list(g))) for k, g in groupby(s)])
    

    l=[]
    for k, g in groupby(s):
        l.append(str(k) + str(len(list(g))))
    
    x= ""
    for s in l:
        x += s
    

    根据文档,“groupby 创建了一个迭代器,它从可迭代对象中返回连续的键和组”。

    举个例子更容易理解。

    print(*[(k,list(g)) for k, g in groupby(s)], sep="\n")
    

    输出:

    ('W', ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W'])
    ('B', ['B'])
    ('W', ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W'])
    ('B', ['B', 'B', 'B'])
    ('W', ['W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W', 'W'])
    ('B', ['B'])
    

    实际上,groupby 返回的迭代器中的每个元素都是一个char c,并带有一个指向所有连续chars c 列表的迭代器。

    在您的代码中,您首先创建一个包含所有对的列表(c,c 出现的连续次数):

    x1 = ['{}{}'.format(k, len(list(g))) for k, g in groupby(s)]
    # ['W12', 'B1', 'W12', 'B3', 'W24', 'B1']
    

    然后将列表中的所有元素连接在一起以创建单个字符串

    x2 = "".join(x1)
    # W12B1W12B3W24B1
    

    【讨论】:

      猜你喜欢
      • 2013-02-01
      • 2012-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多