将字符串拆分为"x"长度的组
我在想,如果我有一个从文本文件中读取的字符串,最有效的方法是什么来把它分成每5个字符一组?比如说:
我有一个叫做 dna.txt 的文本文件,里面的内容是:
>human
ACCGTGAAAAACGTGAGTATA
>mouse
ACCAAAAGTGTAT
然后我有一个 Python 脚本,它会存储这个文本文件的第2行和第4行。
import linecache
f = open("dna.txt")
sequence_1 = linecache.getline('dna.txt', 2)
sequence_2 = linecache.getline('dna.txt', 4)
f.close()
这个程序的目标是打印出:
>human
ACCGT
GAAAA
ACGTG
AGTAT
A
>mouse
ACCAA
AAGTG
TAT
就像我之前说的,我一直在努力想出一种有效的方法来分割这两个字符串,但一直没有成功。非常感谢任何帮助!
6 个回答
你可以很简单地用生成器表达式或者列表推导式来实现这个功能,特别是在旧版本的Python中。对于任何字符串 s
和字符串中的索引 i
,表达式 s[i:i+5]
会返回从位置 i
开始的最长5个字符的子字符串。
如果 i+5
超过了字符串的末尾,使用这种切片的方式会自动处理这个问题,不会报错,而是返回它能找到的最长字符串。
所以这个表达式
[sequence_1[i:i+5] for i in range((0, len(sequence_1), 5)]
应该能给你一个你需要的子字符串列表。
在使用这个之前,先看看我写这个的时候其他人给出的答案。
这个算法很简单,但效率不是很好。
虽然不是特别高效,但你可以用一个简单的循环来实现。
str = "abcdefghijlkmnopqrstuvwxyz"
length = len(str)
i = 0
subs = []
while (i < length):
subs[i/5] = str[i:i+5]
i += 5
最终每个subs的索引应该包含五个字符分组。
In [1]: import re
In [2]: s = "ACCGTGAAAAACGTGAGTATA"
In [3]: print("\n".join(re.findall("\w{5}|\w+",s)))
ACCGT
GAAAA
ACGTG
AGTAT
A
re.findall("\w{5}|\w+",s)
这个代码的意思是从字符串中找出连续的5个字符,或者找出一个或多个字符。
这里有一些时间记录:
In [72]: %timeit "\n".join(groupdna(s,5))
100000 loops, best of 3: 3.5 µs per loop
In [73]: timeit ('\n'.join(splitn(s, 5)))
100000 loops, best of 3: 2.22 µs per loop
In [74]: %timeit re.sub(r'(.{5})(?!$)', r'\g<1>\n', s)
100000 loops, best of 3: 5.24 µs per loop
In [75]: %timeit ("\n".join(re.findall("\w{5}|\w+",s)))
100000 loops, best of 3: 2.16 µs per loop
这段代码可以帮助你入门:
human = "ACCGTGAAAAACGTGAGTATA"
print(' '.join(human[i:i+5] for i in range(0, len(human), 5)))
你可以很简单地把这个变成一个生成器,接受 human
和 5
作为参数,然后输出子字符串:
def splitn(s, n):
for i in range(0, len(s), n):
yield s[i:i+n]
print(' '.join(splitn("ACCGTGAAAAACGTGAGTATA", 5)))
>>> human = 'ACCGTGAAAAACGTGAGTATA'
>>> mouse = 'ACCAAAAGTGTAT'
>>> import re
>>> def format_dna(s):
... return re.sub(r'(.{5})(?!$)', r'\g<1>\n', s)
...
>>> print(format_dna(human))
ACCGT
GAAAA
ACGTG
AGTAT
A
>>> print(format_dna(mouse))
ACCAA
AAGTG
TAT
re.sub
是用来在字符串中进行正则表达式替换的。
(.{5})(?!$)
是用来匹配的模式。\g<1>\n
是用来替换的模式。
.{5}
可以匹配任意五个字符。加上括号 (.{5})
后,它就变成了一个捕获组。
$
表示字符串的结尾。(?!$)
是一种负向前瞻,它的作用是防止匹配到最后一组字符,如果字符串的长度是五的倍数的话(这样会导致在字符串末尾多加一个换行符)。
\g<1>
是一个反向引用,指的是第一个(也是唯一的)捕获组。
所以这段话的意思是:当你看到一连串的五个字符(并且这些不是最后五个字符),就把它们替换成这五个字符加上一个换行符。