将列表压缩为重复的字符串
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
。
【讨论】:
以上是关于将列表压缩为重复的字符串的主要内容,如果未能解决你的问题,请参考以下文章