Python 函数将字符串存储为int
我有一个固定的32位,用来存储尽可能多的DNA。由于只有4种组合,因此存储DNA‘A’、‘C’、‘G’或‘T’的1个字符所需的空间量为2位00、01、10、11 要存储最多2个字符,因此,A、C、G、T、AA、AC、…、GG有20种可能的组合,我们可以使用函数4**x+1-2/4-1计算出来,其中x是我们要存储的DNA的最大长度。因此,16个DNA字符将有5726623060个组合,但在32位中,我最多只能存储4294967296个数字2**32 长话短说,在32位中,一个人可以存储的可变长度DNA的最大数量是15个字母1431655764个组合 所以,下一步是制作一个函数,它将多达15个DNA字母作为一个字符串,并将其转换为一个数字。哪一个数字“A”可以是0,也可以是1,也可以是1332904,这并不重要,只要我们可以反转函数,稍后将数字返回到“A” 我开始通过制作包含1431655764个元素的键值对字典来解决这个问题,但很快就耗尽了RAM。这就是为什么我需要一个从字符串到int的转换函数。这是我的建议 如果存储字母需要2到30位,那么至少还有2位可以帮助您推断长度。始终在代表字符的位后添加1,并用零填充其余部分。这样,如果您查找位模式中的最后一个1,它将始终位于字符串末尾之后 例如Python 函数将字符串存储为int,python,bioinformatics,dna-sequence,Python,Bioinformatics,Dna Sequence,我有一个固定的32位,用来存储尽可能多的DNA。由于只有4种组合,因此存储DNA‘A’、‘C’、‘G’或‘T’的1个字符所需的空间量为2位00、01、10、11 要存储最多2个字符,因此,A、C、G、T、AA、AC、…、GG有20种可能的组合,我们可以使用函数4**x+1-2/4-1计算出来,其中x是我们要存储的DNA的最大长度。因此,16个DNA字符将有5726623060个组合,但在32位中,我最多只能存储4294967296个数字2**32 长话短说,在32位中,一个人可以存储的可变长度D
这应该明确地表示字符串,并允许您在32位中最多包含15个字符。给定静态顺序,您可以将每个排列引用为表示其在序列中顺序的单个数字。然后,您可以在另一端转换词典,而不是构建词典
import itertools
def build_sequence(length):
return itertools.product("ACTG", repeat=length)
def encode(sequence: str):
seq = build_sequence(len(str))
t_seq = list(sequence) # to compare to seq
for idx, s in enumerate(seq):
if s == t_seq:
return idx
def decode(e_sequence):
max_length = math.ceil(math.log(e_sequence, 4))
# max_length is the character count of ATCGs that e_sequence contains,
# since each sequence has 4**length elements
seq = build_sequence(max_length)
for _ in range(e_sequence):
# skipping these is like indexing a list
next(seq)
return next(seq)
然后,您可以将该数字打包成一个较小的类型,并通过网络发送,再次解压缩,然后解码
import struct
packed = struct.pack("I", encode(some_sequence))
# send it? I'm not sure what you're doing with it
rcvd_pack = b'SUUU'
unpacked = struct.unpack("I", rcvd_pack)
# becomes a tuple of the value
enc_seq = unpacked[0]
result = decode(enc_seq)
这应该可以让您构建16个字符的序列,并将它们打包到32位数据中。使用Khelwood的信息,我用以下代码解决了它:
b = {'A':0b00,'C':0b01,'G':0b10,'T':0b11}
t = {'00':'A','01':'C','10':'G','11':'T'}
def binarize(string):
result = 0
for char in (string + 'G').ljust(16,'A'): result = (result << 2) + d[char]
return result
def textualize(value):
result = ''
for twobits in [ format(value, '032b')[i:i+2] for i in range(0,32,2) ]:
result += t[twobits]
return result.rstrip('A')[:-1]
>>> binarize('TTTTTTTTTTTTTTT')
4294967294
>>> textualize(4294967294)
u'TTTTTTTTTTTTTTT'
我相信有一种更有效的方法来完成这一切,我想我需要这样做,因为我将编码和解码数十亿次,但现在它至少起作用:一旦确定可以将每个字符存储在两位中,我不确定您遇到的困难是什么。你有代码吗?只有当字符串长度不变时,每个字母2位才有效。例如,在4位中,我可以用0000表示“AA”,但不能单独表示“A”。有20种DNA组合,只有16个值可以存储在4位中。在这种情况下,您有额外的信息,即字符串的长度,这将需要额外的空间进行编码。为什么您会拒绝投票,并提交一个没有先前解决方案的帖子的接近投票,并且没有任何原因!?因为你的问题归根结底是给我一个代码,这是一个愚蠢的提议,因为你试图在内存非常有限的环境中使用Python。这是一个坏主意,因为同样的原因,你不使用水彩画的数字。它变得邋遢了。使用一种不进行内存管理的语言谢谢你,亚当,我从了解代码的工作原理中学到了很多:我把它放在一个numpy数组中,但是我使用的struct与你描述的完全一样。唯一的问题是,当您浏览itertools.product时,编码15g需要很长时间。但它确实有效,而且很优雅。math.ceilmath.logseq,4是我的秘方:@J.J同意,是的。你应该可以用数学的方法来计算,但我没有时间去弄清楚这些案例是如何运作的。它将类似于二进制编码,但我认为是以4为基数而不是以2为基数?我数学不太清楚
b = {'A':0b00,'C':0b01,'G':0b10,'T':0b11}
t = {'00':'A','01':'C','10':'G','11':'T'}
def binarize(string):
result = 0
for char in (string + 'G').ljust(16,'A'): result = (result << 2) + d[char]
return result
def textualize(value):
result = ''
for twobits in [ format(value, '032b')[i:i+2] for i in range(0,32,2) ]:
result += t[twobits]
return result.rstrip('A')[:-1]
>>> binarize('TTTTTTTTTTTTTTT')
4294967294
>>> textualize(4294967294)
u'TTTTTTTTTTTTTTT'