Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 字符串上的单交换_Python_String_Algorithm_Bioinformatics - Fatal编程技术网

Python 字符串上的单交换

Python 字符串上的单交换,python,string,algorithm,bioinformatics,Python,String,Algorithm,Bioinformatics,我需要找到一种更快的方法,以以下方式在8-11字符串中查找交换: 给定字符串“stdilgnley”,查找字母的所有单字母交换: list_AA = ['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V'] i、 e,对于字符串中的每个字母,用列表中的一个替换原始字符串中的每个字母。产出将是: atdilgnley RTDILGN

我需要找到一种更快的方法,以以下方式在8-11字符串中查找交换:

给定字符串“stdilgnley”,查找字母的所有单字母交换:

list_AA = ['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M',
           'F', 'P', 'S', 'T', 'W', 'Y', 'V']
i、 e,对于字符串中的每个字母,用
列表中的一个替换原始字符串中的每个字母。产出将是:

atdilgnley
RTDILGNLYE
恩蒂尔格尼
...
萨迪尔格尼
斯迪尔格尼
斯迪尔格尼
...
...
斯特迪尔格尼夫
总共200个新串(串中每个位置20个交换)。 到目前为止,我所拥有的:

def _create_swaps(original_str):
    list_peps = []
    for i in range(len(original_str)):
        for k in range(len(list_AA)):
            list_peps.append(_insert_aa(original_str, i, list_aa[k]))

    #remove original string
    return [i for i in list_peps if i != original_str]


def _insert_aa(string, index, aa):
    list_string_elements = list(string)
    del list_string_elements[index]
    hash_string.insert(index, aa)
    return "".join(hash_string)
由于这需要重复10**6次,这是大型项目中最慢的步骤。是否有一种更快地找到此类掉期的方法(通过消除
”。加入
、插入、步骤/通过动态查找掉期)

供参考:

ncalls tottime percall cumtime percall文件名:lineno(函数)
185275200 330.286 0.000 429.295 0.000型号。py:233(_insert_aa)
975240 147.322 0.000 616.979 0.001型号。py:225(_创建_交换)
185280201/185280197 59.137 0.000 59.138 0.000{“str”对象的方法“连接”}
185275208 39.8750.000 39.8750.000{“列表”对象的“插入”方法}
975240 21.027 0.000 21.027 0.000型号。py:231()
186746064 18.516 0.000 18.516 0.000{“列表”对象的“附加”方法}
这应该更快:

def _insert_aa(string, index, aa):
    return string[0:index] + aa + string[index+1:]
编辑:只能对头部和尾部进行一次切片,并按如下方式重复使用:

def generate_all_variants(string, replacements):
    for i in range(len(string)):
        head = string[:i]
        tail = string[i+1:]
        for letter in replacements:
            yield head + letter + tail

for variant in generate_all_variants("abcd",  ['1', '2', '3']):
    print(variant)

这是一个更清晰的版本,你正在寻找的,即使你已经选择了一个答案(它不是最pythonic)

您永远不应该使用range来获取iterable的索引,如果您想对其进行pythonic处理,应该使用enumerate

>>> def swaps(s, lst):
...   for index, _ in enumerate(s):
...     for letter in lst:
...       temp = list(s)
...       temp[index] = letter
...       yield ''.join(temp)
...
>>> list_AA = ['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F', 'P', 'S', 'T', 'W', 'Y', 'V']
>>> s = 'STDILGNLYE'
>>>
>>> for _ in swaps(s, list_AA):
...   print _
...
ATDILGNLYE
RTDILGNLYE
NTDILGNLYE
..........
GTDILGNLYE
HTDILGNLYE
ITDILGNLYE
另外,python3中的一种简化方法:

>>> def swaps(s, lst):
...   for i, _ in enumerate(s):
...     yield from ['%s%s%s' % (s[:i], x, s[i+1:]) for x in lst]
...
>>> swaps(s,list_AA)
<generator object swaps at 0x10c9205c8>
>>> a=_
>>> next(a)
'ATDILGNLYE'
>>> next(a)
'RTDILGNLYE'
>>> next(a)
'NTDILGNLYE'
>>> next(a)
'DTDILGNLYE'

以下是对这三个方面的基准测试:

s='STDILGNLYE'
list_AA=['A', 'R', 'N', 'D', 'C', 'Q', 'E', 'G', 'H', 'I', 'L', 'K', 'M', 'F',
        'P', 'S', 'T', 'W', 'Y', 'V']

# the correct sample size
list_new = list_AA * (10**6 // len(list_AA))

def swaps0(string, replacements):
    for i in range(len(string)):
        head = string[:i]
        tail = string[i+1:]
        for letter in replacements:
            yield head + letter + tail

def swaps1(s, lst):
  for i, _ in enumerate(s):
    yield from ['%s%s%s' % (s[:i], x, s[i+1:]) for x in lst]

def swaps2(s, lst):
  for index, _ in enumerate(s):
    for letter in lst:
      temp = list(s)
      temp[index] = letter
      yield ''.join(temp)

timeit [_ for _ in swaps0(s, list_new)]
timeit [_ for _ in swaps1(s, list_new)]
timeit [_ for _ in swaps2(s, list_new)]


In [9]: timeit [_ for _ in swaps0(s, list_new)]
1 loop, best of 3: 2.61 s per loop
In [10]: timeit [_ for _ in swaps1(s, list_new)]
1 loop, best of 3: 6.57 s per loop
In [11]: timeit [_ for _ in swaps2(s, list_new)]
1 loop, best of 3: 8.61 s per loop
值得吗?我想说,这取决于您希望这个样本大小增长多少,以及您运行代码的频率

如果代码不会频繁运行(比如,每小时数百次),并且样本量不会呈指数增长(达到1050或10100),那么我会说要提高可读性

如果要随着样本量的增加而频繁地计算,那么就考虑性能

最后,我们剩下一个折衷的解决方案,将枚举与头/尾拆分相结合:

def swap3(s, lst):
    for i, _ in enumerate(s):
        head, tail = s[:i], s[i+1:]
        yield from ['%s%s%s'%(head,c,tail) for c in lst]

In [16]: timeit [_ for _ in swap3(s, list_new)]
1 loop, best of 3: 3.99 s per loop

你需要发出所有生成的字符串,还是只需要数一数?@Steve我需要所有的字符串。正如您从
\u create\u swaps
的返回调用中所看到的,它返回除原始字符串之外的所有已创建字符串。您可能想尝试找出一种方法,用
映射()替换其中一个操作。
…请参见循环效率…当然,分析总是比理论上的好。
“”.join
总是比使用
+
进行连接更快。您的编辑似乎是我正在寻找的解决方案。不过,为什么要坚持使用
+
而不是
”。join
?join函数只使用一个参数,通常是一个列表,但创建列表需要时间。@Carlo
”。join
并不总是更快。对于短字符串,尤其是长度小于10的字符串,由于产生的开销,它的速度通常较慢。但是,切片和连接速度更快。timeit变量=[v代表v在生成所有变量(s,列表AA)]10000个循环,每个循环的最佳值为3:34.3µs timeit变量=[v代表v在交换(s,列表AA)]1000个循环,每个循环的最佳值为3:271µsloop@steve我用一种更简单的方法更新了我的答案,使用了Python3Also,python的“禅”就是这么简单,可读代码比有微优化的丑陋代码要好。优化只是一个微观优化。您需要替换大量字符才能显著提高速度。@CharlesAddis事实上,对于这一特定目的,最好使用微优化,因为我将对大量字符串执行交换,正如我所指出的。这是我代码中最大的瓶颈。不管怎样,谢谢你的输入,我从你的答案中学到了一两件事。值得一提的是,将其转换为C可以提高速度。您可以通过使用Cython获得一些重要的优化。另一方面,在我的一个高级项目中,将图形操作从Python转换为C可以减少约6个数量级的处理时间,因为在C中,您可以更有效地处理图形,而无需所有开销。(>30小时vs
def swap3(s, lst):
    for i, _ in enumerate(s):
        head, tail = s[:i], s[i+1:]
        yield from ['%s%s%s'%(head,c,tail) for c in lst]

In [16]: timeit [_ for _ in swap3(s, list_new)]
1 loop, best of 3: 3.99 s per loop