我刚刚开始学习python,我有这个让我感到困惑的练习: 创建一个可以打包或解包字母串的函数。 所以aaabb将被打包a3b2,反之亦然。
对于函数的打包部分,我写了以下
def packer(s):
if s.isalpha(): # Defines if unpacked
stack = []
for i in s:
if s.count(i) > 1:
if (i + str(s.count(i))) not in stack:
stack.append(i + str(s.count(i)))
else:
stack.append(i)
print "".join(stack)
else:
print "Something's not quite right.."
return False
packer("aaaaaaaaaaaabbbccccd")
这似乎一切正常。但作业说明了这一点 如果输入有(例如)b或c之后的字母a,那么 它应该在以后解压缩成原始形式。 所以“aaabbkka”应该变成a3b2k2a,而不是a4b2k2。 因此我想,我不能使用“count()”命令,因为 计算整个字符串中所有项目的出现次数,对吗? 那么我的选择是什么呢?
打开包装 - 我已经想到了我的代码需要做的基础知识 -
创建一个for循环,并在其中包含一个if语句,然后检查每个元素:
2.1。如果它后面有一个数字>返回(或添加到空堆栈)数字乘以数字
2.2。如果它之后没有数字>只返回元素。
第2号大问题 - 我如何检查它是一个数字还是另一个数字 列表中元素后面的字母元素?我想这一定必须完成 切片,但那些只采取整数。这可以通过索引命令来实现吗?
此外 - 如果这有任何相关性 - 到目前为止我基本上涵盖了列表,字符串,if和for 而且我被告知这种练习对那些练习是可行的(......所以如果你不介意保持这个非常基础)
所有帮助对新手爱好者表示赞赏!
解决:
def packer(s):
if s.isalpha(): # Defines if unpacked
groups= []
last_char = None
for c in s:
if c == last_char:
groups[-1].append(c)
else:
groups.append([c])
last_char = c
return ''.join('%s%s' % (g[0], len(g)>1 and len(g) or '') for g in groups)
else: # Seems to be packed
stack = ""
for i in range(len(s)):
if s[i].isalpha():
if i+1 < len(s) and s[i+1].isdigit():
digit = s[i+1]
char = s[i]
i += 2
while i < len(s) and s[i].isdigit():
digit +=s[i]
i+=1
stack += char * int(digit)
else:
stack+= s[i]
else:
""
return "".join(stack)
print (packer("aaaaaaaaaaaabbbccccd"))
print (packer("a4b19am4nmba22"))
所以这是我的最终代码。几乎设法用for循环和if语句来完成它。 最后虽然我不得不引入while循环来解决读取多位数的问题。我想我仍然设法保持足够简单。非常感谢他们和其他所有人一起切入!
答案 0 :(得分:2)
我认为您可以使用`itertools.grouby'功能
例如
import itertools
data = 'aaassaaasssddee'
groupped_data = ((c, len(list(g))) for c, g in itertools.groupby(data))
result = ''.join(c + (str(n) if n > 1 else '') for c, n in groupped_data)
当然可以使用generator而不是generator语句使这段代码更具可读性
答案 1 :(得分:2)
一个简单的解决方案: 如果char不同,请创建一个新组。否则将其附加到最后一组。最后计算所有组并加入它们。
def packer(s):
groups = []
last_char = None
for c in s:
if c == last_char:
groups[-1].append(c)
else:
groups.append([c])
last_char = c
return ''.join('%s%s'%(g[0], len(g)) for g in groups)
另一种方法是使用re
。
正则表达式r'(.)\1+'
可以匹配长于1的连续字符。使用re.sub
,您可以轻松对其进行编码:
regex = re.compile(r'(.)\1+')
def replacer(match):
return match.group(1) + str(len(match.group(0)))
regex.sub(replacer, 'aaabbkka')
#=> 'a3b2k2a'
答案 2 :(得分:2)
这是我在评论中概述的算法的实现:
from itertools import takewhile, count, islice, izip
def consume(items):
from collections import deque
deque(items, maxlen=0)
def ilen(items):
result = count()
consume(izip(items, result))
return next(result)
def pack_or_unpack(data):
start = 0
result = []
while start < len(data):
if data[start].isdigit():
# `data` is packed, bail
return unpack(data)
run = run_len(data, start)
# append the character that might repeat
result.append(data[start])
if run > 1:
# append the length of the run of characters
result.append(str(run))
start += run
return ''.join(result)
def run_len(data, start):
"""Return the end index of the run of identical characters starting at
`start`"""
return start + ilen(takewhile(lambda c: c == data[start],
islice(data, start, None)))
def unpack(data):
result = []
for i in range(len(data)):
if data[i].isdigit():
# skip digits, we'll look for them below
continue
# packed character
c = data[i]
# number of repetitions
n = 1
if (i+1) < len(data) and data[i+1].isdigit():
# if the next character is a digit, grab all the digits in the
# substring starting at i+1
n = int(''.join(takewhile(str.isdigit, data[i+1:])))
# append the repeated character
result.append(c*n) # multiplying a string with a number repeats it
return ''.join(result)
print pack_or_unpack('aaabbc')
print pack_or_unpack('a3b2c')
print pack_or_unpack('a10')
print pack_or_unpack('b5c5')
print pack_or_unpack('abc')
unpack()
的正则表达式版本将是:
import re
UNPACK_RE = re.compile(r'(?P<char> [a-zA-Z]) (?P<count> \d+)?', re.VERBOSE)
def unpack_re(data):
matches = UNPACK_RE.finditer(data)
pairs = ((m.group('char'), m.group('count')) for m in matches)
return ''.join(char * (int(count) if count else 1)
for char, count in pairs)
此代码演示了实现该算法的最简单(或“基本”)方法。它不是特别优雅或惯用或必然有效。 (如果用C语言编写,但Python有一些注意事项,例如:索引字符串会将字符复制到新字符串中,而似乎过度复制数据的算法可能比尝试避免这种情况更快,如果复制完成的话C和解决方法是用Python循环实现的。)