【问题标题】:How to make a for loop use 2 strings?如何使 for 循环使用 2 个字符串?
【发布时间】:2014-07-16 17:49:22
【问题描述】:

我有 2 个字符串要比较。问题是我不知道如何同时对两个切片进行迭代,然后在每个切片上运行比较代码。下面是我尝试通过在 for 循环中使用 for 循环来运行的代码(每个字符串一个) 这没有带来任何错误,但只有第一个字符串被迭代切片并打印到屏幕上。第二次尝试是将 2 个 for 循环合并在一起,但是出现了提供的错误消息,它清楚地解释了失败的原因,但是我不知道解决该错误的方法。

for循环中for循环的代码

for i in range(8, len(seq1)):
    seq1i = seq1[0:i]
    print seq1i

    for i in range(8,len(seq2)):
        seq2i = seq2[0:i]
        print seq2i

        for c1, c2 in zip(seq1i, seq2i):
            if c1 == c2:
                counter += 1
            else:
                break
        print "String share the longest common prefix of length %d: %s" % (counter, seq1[:counter])
        if counter >= 8:
            print " Match found, match length %d" % counter

尝试合并 for 循环:

for i1,i2 in range(8,len(seq1, seq2)):
    for c1, c2 in zip(seq1i, seq2i):
        if c1 == c2:
            counter += 1
        else:
            break
    print "String share the longest common prefix of length %d: %s" % (counter, seq1[:counter])
    if counter >= 8:
        print " Match found, match length %d" % counter

这导致了错误:

TypeError                                 Traceback (most recent call last)
<ipython-input-26-9c4822069792> in <module>()
----> 1 for i1,i2 in range(8,len(seq1, seq2)):
      2     for c1, c2 in zip(seq1i, seq2i):
      3         if c1 == c2:
      4             counter += 1
      5         else:

TypeError: len() takes exactly one argument (2 given)

我认为必须有一种方法可以对字符串进行每次迭代切片,并且在制作它们时可以运行匹配的(如果 c1 == c2)代码。

想要的输出是:

如果 seq1 和 seq2:

seq1 = 'ATCGATCGATCGAAAA'
seq2 = 'ATCGATCGATCCCCCC'

A
A
AT
AT
ATC
ATC
ATCG
ATCG
ATCGA
ATCGA
ATCGAT
ATCGAT
ATCGATC
ATCGATC
ATCGATCG
ATCGATCG
ATCGATCGA
ATCGATCGA
ATCGATCGAT
ATCGATCGAT
ATCGATCGATC
ATCGATCGATC
String share the longest common prefix of length 10:ATCGATCGATC

【问题讨论】:

  • 你基本上想做什么?

标签: python python-2.7 slice


【解决方案1】:

我确信使用高级切片和/或 itertools 有更好的解决方案,但老实说,我认为一个简单的循环是这里最简单的事情。

for i, c in enumerate(seq1):
    try:
        if c != seq2[i]:
            break
        print seq1[:i + 1] + '\n' + seq1[:i + 1]
    except IndexError:
        break
print 'Longest common prefix %s of length %d' % (seq1[:i], i)

【讨论】:

  • 如果seq1seq2 长,可能会出现索引错误。
  • @martineau 这就是if 被包裹在try 中的原因。
【解决方案2】:

尽管来自os.path 模块,但您应该为此使用os.path.commonprefix

>> s1 = 'GATTACA'
>> s2 = 'GATTCCC'
>> os.path.commonprefix([s1,s2])
'GATT'

【讨论】:

  • 只要记得写个很清晰的注释...说说晦涩的代码用法...
  • 我可以理解为什么它看起来晦涩难懂,并且我同意在某些模块中拥有一个不是 os.path 的库函数会很好,但是没有理由重新发明轮子来做常用前缀。
  • 除了它是一个非常简单的轮子,它的重新发明让你的代码更清晰......
  • @SilasRay 我不知道我是否同意你的看法。使用来自 stdlib 的方法,即使它被归类为 os.path 并用于其他用途,也不会比编写一个新的自定义函数(您还必须为其记录)具有相同的功能更有意义。跨度>
  • 正如这个问题所暗示的,有几种方法可以错误地重新发明轮子。我同意这很烦人,并且肯定应该在其他地方(如果你用谷歌搜索,你会发现人们对它只进行字符串操作而没有进行更智能的路径检查感到非常恼火,我个人只是有点心理请注意,os.path.commonprefix 实际上并不是os.path 的一部分)
【解决方案3】:

打印中间结果有点低效,但这似乎可行:

def lcp(seq1, seq2):
    ret = []
    for i in xrange(min(len(seq1), len(seq1))):
        if seq1[i] != seq2[i]:
            break
        else:
            ret.append(seq1[i])
            print ''.join(ret)
    print "strings share a longest common prefix of length:", len(ret)

seq1 = 'ATCGATCGATCGAAAA'
seq2 = 'ATCGATCGATCCCCCC'
lcp(seq1, seq2)

输出:

A
AT
ATC
ATCG
ATCGA
ATCGAT
ATCGATC
ATCGATCG
ATCGATCGA
ATCGATCGAT
ATCGATCGATC
strings share a longest common prefix of length: 11

【讨论】:

    【解决方案4】:

    您实际上可以zip 字符串,这似乎比这里的大多数答案更pythonic:

    str1 = 'ACTGGAG'
    str2 = 'ACTA'
    
    prefix = ''
    for a,b in zip(str1,str2):
        if a==b:
            prefix += a
        else:
            break
    
    print prefix # prints ACT
    

    【讨论】:

    • 是否可以设置匹配异常,以便如果 a 或 b = 'N' 继续匹配?
    • 当然,只需将 "a==b" 更改为 "a==b or a=='N' or b=='N'" 或者如果您想要一些特殊行为(比如在前缀中添加特殊字符)
    猜你喜欢
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    • 2014-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多