将列表压缩为重复的字符串

Posted

技术标签:

【中文标题】将列表压缩为重复的字符串【英文标题】:Compress a list to string with repetition 【发布时间】:2018-11-23 03:01:39 【问题描述】:

逻辑:将列表压缩为字符串,其中列表中重复两次的字母在结果字符串中重复指定次数。

例子:

['a','a',2,'b','c','c',3], --> aabccc ['a,','a',2] --> aa ['c','c',3] --> ccc.

我的代码是:

def run_length_decoder(in_list):
list=[]
for i in range(0,len(in_list)-1):
    if in_list[i]==in_list[i+1]:
        for x in range((i+2)-1):
            list.append(in_list[i])
    else:
        list.append(in_list[i])
list.append(in_list[-1])
word = ""
for letter in list:
    word += str(letter)
return word

这不起作用...因为使用['a', 'a', 2, 'b', 'b', 2, 'a', 'b', 'a'] 运行上述命令会返回'aaa2bbbbbb2aba',但应该返回'aabbaba'

【问题讨论】:

for x in range((i+2)-1): 应该是for x in range(in_list[i + 2]): 您确定编码列表吗?感觉像是一种奇怪的编码方式。 "".join(["" if isinstance(letter, int) else letter for letter in list]) @Avezan,这行不通,因为['c', 'c', 3] 应该返回'ccc' @jpp 我出去了,不懂逻辑... 【参考方案1】:

看起来很复杂。对于初学者,您应该更正缩进。此外,由于数字计数器是可选的,因此您需要添加逻辑来识别整数与字符串。最后,由于字母的数量不需要与以下计数器同步,因此您需要明确地为每个计数器附加一个字母。

您可以通过itertools.groupby 和列表理解来做到这一点。

from itertools import groupby, zip_longest

L = ['a', 'a', 2, 'b', 'b', 2, 'a', 'b', 'a']

L2 = [i for i, _ in groupby(L)]

res = ''.join([i*(j if isinstance(j, int) else 1)
               for i, j in zip_longest(L2, L2[1:])
               if isinstance(i, str)])

print(res)

aabbaba

【讨论】:

【参考方案2】:

您可以在 while 循环中使用解包 itertools.groupby

import itertools
def group_data(f):
  def wrapper(_s):
    return list(f([[a, list(b)] for a, b in itertools.groupby(_s, key=lambda x:isinstance(x, str))]))
  return wrapper

@group_data
def decompress(stream): 
  while stream:
    if len(stream) == 1:
       [[_, v]] = stream
       yield v
       stream = []
    else:
       [flag, a], [flag2, b], *_stream = stream
       if flag and not flag2:
         yield a if b[0] ==2 else [a[-1]]*b[0] if len(set(a)) == 1 else [*a[:-1], *([a[-1]]*b[0])]
         stream = _stream
       else:
         yield a
         stream = [[flag, b], *_stream]

data = [['a', 'a', 2, 'b', 'b', 2, 'a', 'b', 'a'], ['a', 'a', 3, 'b', 'b', 2, 'a', 'b', 'a', 3]]
new_result = list(map(lambda x:''.join(''.join(i) for i in decompress(x)), data))

输出:

['aabbaba', 'aaabbabaaa']

【讨论】:

【参考方案3】:

使用生成器功能:

def repeat(x):
    def _repeat(x):
        it = iter(x)
        last = nxt = next(it)
        yield last
        while it:
            try:
                last = nxt
                nxt = next(it)
            except StopIteration:
                # See PEP 479 / new handling in Python 3.5
                break
            if isinstance(nxt, str):
                yield nxt
            elif isinstance(nxt, int):
                rpt = nxt - 2
                if rpt:
                    yield last * rpt
    return ''.join(_repeat(x))

>>> x = ['a', 'a', 2, 'b', 'c', 'c', 3]
>>> repeat(x)
'aabccc'

>>> y = ['a', 'a', 2, 'b', 'b', 2, 'a', 'b', 'a']
>>> repeat(y)
'aabbaba'

>>> repeat(['c', 'c', 3])
'ccc'

内部函数说,“继续前进/让步,直到遇到int n。”当它被击中时,重复之前看到的字符 n - 2 次。

从 Python 3.5 开始,需要明确地 checking 用于 StopIteration

【讨论】:

以上是关于将列表压缩为重复的字符串的主要内容,如果未能解决你的问题,请参考以下文章

将字符串列表转换为整数列表[重复]

将列表转换为字符串[重复]

如何将列表转换为字符串[重复]

将字符列表转换为字符串[重复]

Java将字符串转换为枚举列表[重复]

将字符串列表转换为一个字符串[重复]