将 5A2B4C11G 字符串转换为 [(5,"A"),(2,"B"),(4,"C"),(11,"G")] in Python
Convert 5A2B4C11G string to [(5,"A"),(2,"B"),(4,"C"),(11,"G")] in Python
标题几乎说明了一切。我有一个小的run-length解码脚本:
def RLdecode(characterList):
decodedString = ""
for character, count in characterList:
decodedString += character.upper() * count
return decodedString
该脚本需要一个如下所示的列表(或其他任何内容):
[(5,"A"),(2,"B"),(4,"C"),(11,"G")]
但是为了让它更user-friendly,我希望用户能够输入这样的字符串:
"5A2B4C11G"
如何将上面的字符串转换为我的脚本可读的列表?另外,抱歉,问题的标题很具体,但我不知道这个过程叫什么:\
使用list comprehension
:
#s is the string
[(int(s[i]),s[i+1]) for i in range(0,len(s),2)]
#驱动值
IN : s="5A2B4C"
OUT : [(5, 'A'), (2, 'B'), (4, 'C')]
这里 range(0,len(s),2)
给出的值是:[0, 2, 4]
我们用它来遍历 string
.
注意: 本课程仅适用于 even
大小的字符串和小于 10 的数字。
编辑: 至于两位数的数字, 的答案很好。
如果需要,您可以使用正则表达式执行此操作:
In one line
sorted_list=[i for i in re.findall(pattern, a, re.M)]
同样的方法:
import re
a="5A2B4C"
pattern=r'(\d)(\w)'
list=[]
art=re.findall(pattern,a,re.M)
for i in art:
list.append(i)
print(list)
对于您新编辑的问题,这是我的新解决方案:
import re
a = "5A2B4C11G"
pattern = r'([0-9]+)([a-zA-Z])'
list = []
art = re.findall(pattern, a, re.M)
for i in art:
list.append(i)
print(list)
Output:
[('5', 'A'), ('2', 'B'), ('4', 'C'), ('11', 'G')]
使用 itertools.groupby
:
有一个很好的方法可以使用 itertools.groupby
:
进行 letter/digit 分组
import itertools
a="5A2B4C11G"
result = [("".join(v)) for k,v in itertools.groupby(a,str.isdigit)]
那个returns['5', 'A', '2', 'B', '4', 'C', '11', 'G']
不幸的是,它使 number/letter 元组变平,因此需要做更多的工作。请注意,现在 number/letter 已正确完成,将 Kaushik 解决方案应用于该输入会产生预期结果:
[(int(result[i]),result[i+1]) for i in range(0,len(result),2)]
结果:
[(5, 'A'), (2, 'B'), (4, 'C'), (11, 'G')]
使用正则表达式:
无论如何,在那种情况下,正则表达式非常适合提取具有所需层次结构的模式。
只需使用 1 个或多个数字 + 一个字母来匹配字符串,并将获得的元组转换为匹配 (integer, string) 格式,使用列表理解在一行中这样做。
import re
a="5A2B4C11G"
result = [(int(i),v) for i,v in re.findall('(\d+)([A-Z])',a)]
print(result)
给出:
[(5, 'A'), (2, 'B'), (4, 'C'), (11, 'G')]
您已经从那里得到了答案。
这个过程就是调用长度解码。
整个过程可以通过以下代码在一个线程中完成。
from re import sub
text = "5A2B4C11G"
sub(r'(\d+)(\D)', lambda m: m.group(2) * int(m.group(1)),text)
OUTPUT : 'AAAAABBCCCCGGGGGGGGGGG'
注意 这不是答案,只是 OP 的优化想法,因为答案已经存在于
import re
str = "5A2B4C11G"
pattern = r"(\d+)(\D)" # group1: digit(s), group2: non-digit
substitution = r", " # "ditits,nondigit "
temp = re.sub(pattern, substitution, str) # gives "5,A 2,B 4,C 11,G "
temp = temp.split() # gives ['5,A', '2,B', '4,C', '11,G']
result = [el.split(",") for el in temp] # gives [['5', 'A'], ['2', 'B'],
# ['4', 'C'], ['11', 'G']] - see note
首先,我们将 digits
后跟 symbol
的序列替换为我们可以应用 2 级 split()
的内容,选择 2 个不同的分隔符 在替换字符串 r", "
space
用于第 1st 级(外部)split(),并且
,
为 2nd 一级(内部)。
然后我们应用这 2 个拆分。
注意:如果你有重要的理由获得tuples
(而不是足够好的内部lists
),只需应用tuple()
最后语句中的函数:
result = [tuple(el.split(",")) for el in temp]
标题几乎说明了一切。我有一个小的run-length解码脚本:
def RLdecode(characterList):
decodedString = ""
for character, count in characterList:
decodedString += character.upper() * count
return decodedString
该脚本需要一个如下所示的列表(或其他任何内容):
[(5,"A"),(2,"B"),(4,"C"),(11,"G")]
但是为了让它更user-friendly,我希望用户能够输入这样的字符串:
"5A2B4C11G"
如何将上面的字符串转换为我的脚本可读的列表?另外,抱歉,问题的标题很具体,但我不知道这个过程叫什么:\
使用list comprehension
:
#s is the string
[(int(s[i]),s[i+1]) for i in range(0,len(s),2)]
#驱动值
IN : s="5A2B4C"
OUT : [(5, 'A'), (2, 'B'), (4, 'C')]
这里 range(0,len(s),2)
给出的值是:[0, 2, 4]
我们用它来遍历 string
.
注意: 本课程仅适用于 even
大小的字符串和小于 10 的数字。
编辑: 至于两位数的数字,
如果需要,您可以使用正则表达式执行此操作:
In one line
sorted_list=[i for i in re.findall(pattern, a, re.M)]
同样的方法:
import re
a="5A2B4C"
pattern=r'(\d)(\w)'
list=[]
art=re.findall(pattern,a,re.M)
for i in art:
list.append(i)
print(list)
对于您新编辑的问题,这是我的新解决方案:
import re
a = "5A2B4C11G"
pattern = r'([0-9]+)([a-zA-Z])'
list = []
art = re.findall(pattern, a, re.M)
for i in art:
list.append(i)
print(list)
Output:
[('5', 'A'), ('2', 'B'), ('4', 'C'), ('11', 'G')]
使用 itertools.groupby
:
有一个很好的方法可以使用 itertools.groupby
:
import itertools
a="5A2B4C11G"
result = [("".join(v)) for k,v in itertools.groupby(a,str.isdigit)]
那个returns['5', 'A', '2', 'B', '4', 'C', '11', 'G']
不幸的是,它使 number/letter 元组变平,因此需要做更多的工作。请注意,现在 number/letter 已正确完成,将 Kaushik 解决方案应用于该输入会产生预期结果:
[(int(result[i]),result[i+1]) for i in range(0,len(result),2)]
结果:
[(5, 'A'), (2, 'B'), (4, 'C'), (11, 'G')]
使用正则表达式:
无论如何,在那种情况下,正则表达式非常适合提取具有所需层次结构的模式。
只需使用 1 个或多个数字 + 一个字母来匹配字符串,并将获得的元组转换为匹配 (integer, string) 格式,使用列表理解在一行中这样做。
import re
a="5A2B4C11G"
result = [(int(i),v) for i,v in re.findall('(\d+)([A-Z])',a)]
print(result)
给出:
[(5, 'A'), (2, 'B'), (4, 'C'), (11, 'G')]
您已经从
整个过程可以通过以下代码在一个线程中完成。
from re import sub
text = "5A2B4C11G"
sub(r'(\d+)(\D)', lambda m: m.group(2) * int(m.group(1)),text)
OUTPUT : 'AAAAABBCCCCGGGGGGGGGGG'
注意 这不是答案,只是 OP 的优化想法,因为答案已经存在于
import re
str = "5A2B4C11G"
pattern = r"(\d+)(\D)" # group1: digit(s), group2: non-digit
substitution = r", " # "ditits,nondigit "
temp = re.sub(pattern, substitution, str) # gives "5,A 2,B 4,C 11,G "
temp = temp.split() # gives ['5,A', '2,B', '4,C', '11,G']
result = [el.split(",") for el in temp] # gives [['5', 'A'], ['2', 'B'],
# ['4', 'C'], ['11', 'G']] - see note
首先,我们将 digits
后跟 symbol
的序列替换为我们可以应用 2 级 split()
的内容,选择 2 个不同的分隔符 在替换字符串 r", "
space
用于第 1st 级(外部)split(),并且,
为 2nd 一级(内部)。
然后我们应用这 2 个拆分。
注意:如果你有重要的理由获得tuples
(而不是足够好的内部lists
),只需应用tuple()
最后语句中的函数:
result = [tuple(el.split(",")) for el in temp]