在朋友那里看到一个很有意思的题目,当然原因可能是我其实比较少有复杂的、递归解题经验,所以就做得很痛苦,其中有一个类似如下的需求:
lst = [0, 1, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 0]
要求:将形如上文中的所有带有0的列表单独截取出来
解决方法
首先想到的是re.findall,所以将整个列表转化成字符串并截取,分成首、尾、中间三种类型来处理:
# 截取开头是0的段落
re.findall('^\[(([0, ]+), [1-9]+)?,',str(lst))
得到 [(‘0, 1’, ‘0’)] ,没有问题
# 截取末尾是0的段落
re.findall('( [1-9]+, ([0, ]+))]$',str(lst))
得到 [(’ 34, 0, 0, 0, 0’, ‘0, 0, 0, 0’)] ,没有问题
中间出问题的部分
# 截取中间是0的段落
re.findall('( ?[1-9]+, ([,0 ]+?), [1-9]+?,)',str(lst))
得到 [(’ 1, 0, 0, 2,’, ‘0, 0’)] ,只拿到了第一段,漏掉了[2,0,0,0,34]
考虑原因是re.findall在第一次获取字符串的时候只对’2’读取一次,后面的字符串就不取‘2’了。
也不知道该怎么解决,就用了一个比较愚蠢的办法,将该列表中所有前后都是0的非零数重复一次:
lst = [0, 1, 0, 0, 2, 0, 0, 0, 34, 0, 0, 0, 0]
for i in range(1, len(lst)-1):
lst = lst[:i+1]+lst[i:] if lst[i] != 0 and lst[i-1] ==0 and lst[i+1] == 0 else lst
print(lst)
得到 lst = [0, 1, 1, 0, 0, 2, 2, 0, 0, 0, 34, 34, 0, 0, 0, 0]
# 再次对新lst截取中间是0的段落
lst = [0, 1, 1, 0, 0, 2, 2, 0, 0, 0, 34, 34, 0, 0, 0, 0]
re.findall('( ?[1-9]+, ([,0 ]+?), [1-9]+?,)',str(lst))
得到 [(’ 1, 0, 0, 2,’, ‘0, 0’), (’ 2, 0, 0, 0, 34,’, ‘0, 0, 0’)] ,成功
整体脚本
def reint(str_mpt):
"""
str还原list函数
"""
return [int(i) for i in str_mpt.replace('[','').replace(']','').split(',') if i not in ['']]
def find0(lst):
"""
找全零
"""
frs = re.findall('^\[(([0, ]+), [1-9]+)?,',str(lst)) # 首
las = re.findall('( [1-9]+, ([0, ]+))]$',str(lst)) # 尾
for i in range(1, len(lst)-1):
lst = lst[:i+1]+lst[i:] if lst[i] != 0 and lst[i-1] ==0 and lst[i+1] == 0 else lst
mdl = re.findall('( ?[1-9]+, ([,0 ]+?), [1-9]+?,)',str(lst)) # 中间
return [(reint(i[0]),reint(i[1])) for i in frs+mdl+las]
得到如下结果,成功但有点蠢,希望有大佬看到本文能给出更好的方法,最想知道的是如何在长字符串中获取某种特定字符串组合的1次以上重复的短字符串,比如从abcd123dcbabcdeaabcabcbcdefadb中获取’abc’的任意重复