【问题标题】:Python str mapping permutation with some limitations and special conditions using recursionPython str 映射排列有一些限制和使用递归的特殊条件
【发布时间】:2018-01-19 01:26:24
【问题描述】:

给定一个字符串作为输入,我需要将 a's 更改为 t's,c's 更改为 g's,u's 更改为 a's,g's 更改为 c's [a-t, c-g, g-c, u-a]。另一个特殊情况是最多有两种情况 u's 转换为 g's 和/或 g's 转换为 t's [u-g, g-t]。

作为例子 -

input : 
    auugca
output : 
    taacgt
    tgacgt
    taatgt
    tggcgt
    tgatgt
    tagtgt

在输出中,

  1. 无特殊变化
  2. 将第二个字符 u 特殊更改为 g
  3. 将第三个字符 u 特殊更改为 g
  4. 将第 4 个字符 g 特殊更改为 t
  5. 第二个和第三个字符的两个特殊变化
  6. 第 2 和第 4 个字符的两个特殊变化
  7. 第 3 和第 4 个字符的两个特殊变化

我是这样想的,

  • 从字符串的开头开始
  • 转换 a-t 和 c-g。
  • 如果找到 u 或 g,检查之前有多少特价商品 遇到,如果小于两个,则视为特殊,递增 以前遇到的计数器,从字符串的下一个位置递归创建两个新搜索,一个有特殊考虑,其他没有

我想出的代码是(在 Python 中) -

 # mirna is the string to be converted
 # wobblecount is the number of specials coneverted
 # location is from which location of the string the convertion will start
 # compliment is the end string to be created


 def createonewobble(mirna, location, wobblecount, compliment):

    for counter in range(location, len(mirna)):
        if (mirna[counter] == 'A' or mirna[counter] == 'a'):
            compliment = compliment + "t"
        elif (mirna[counter] == 'C' or mirna[counter] == 'c'):
            compliment = compliment + "g"
        elif ((mirna[counter] == 'U' or mirna[counter] == 'u') and (wobblecount < 2)):
            compliment = compliment + "g"
            createonewobble(mirna, counter+1 , wobblecount+1, compliment)
            compliment = compliment + "a"
            createonewobble(mirna, counter+1 , wobblecount, compliment)
        elif ((mirna[counter] == 'G' or mirna[counter] == 'g') and (wobblecount < 2)):
            compliment = compliment + "t"
            createonewobble(mirna, counter+1 , wobblecount+1, compliment)
            compliment = compliment + "a"
            createonewobble(mirna, counter+1 , wobblecount, compliment)
        elif ((mirna[counter] == 'U' or mirna[counter] == 'u') and (wobblecount == 2)):
            compliment = compliment + "a"
        elif ((mirna[counter] == 'G' or mirna[counter] == 'g') and (wobblecount == 2)):
            compliment = compliment + "c"

    print compliment


mirna = "auugca"
createonewobble(mirna, 0, 0, "")

输出

tggcgt
tggatgt
tggatagt
tggatagt
tggatgt
tggatagt
tggatagt
tgagtgt
tgagtagt
tgagtagt
tgagatgt
tgagatagt
tgagatagt
tgagatgt
tgagatagt
tgagatagt
tgagtgt
tgagtagt
tgagtagt
tgagatgt
tgagatagt
tgagatagt
tgagatgt
tgagatagt
tgagatagt

这给了我 25 个输出,没有一个正确的输出,而且有些输出的长度远远超过字符串的大小。我哪里错了?

【问题讨论】:

  • 您的代码引用了createonewobble,但没有定义它。请创建演示问题的最短的完整程序。请将该程序以及预期和实际输出复制粘贴(切勿重新输入)到您的问题中。请参阅minimal reproducible example 了解更多信息。
  • @Rob,抱歉,我更改了要转换的函数的名称以使其更具可读性,但在递归调用中忘记了这样做。再次抱歉。
  • 请按现在的样子运行代码,并将实际和预期的结果复制粘贴到您的问题中。
  • 你的逻辑有问题。除了不小心使用convert 作为函数名称而不是createonewobble 的明显拼写错误之外,请考虑每次遇到'g''u' 时,除了您创建的搜索之外,您还创建了两个新搜索'目前正在运行。这就是为什么你会得到很多额外的东西。您可以通过在进入循环之前执行lowmirna = mirna.lower() 之类的操作并消除近一半的比较,并使用列表来跟踪赞美而不是打印它们,从而清楚地知道来自哪里的内容,可以使事情变得更加清晰。跨度>
  • @Feneric,我不明白你要我对字符串的后半部分做什么。

标签: python string recursion


【解决方案1】:

您在这里尝试解决的问题是一种带有一些限制的回溯递归。

您的代码接近解决方案,但是:

  1. 它不是 Pythonic 的,所以很难理解。下次提高您的可读性。
  2. 当您解决排列问题时,您应该使用set 来避免重复。在您的解决方案中,您使用了print,它将为您提供重复的打印件(如果有的话)。
  3. 最重要的是当您调用递归函数时,您将 compliment 变量传递给它,该变量之前已修改,现在不再有效。

为了解释第 3 点,我们来看看你的代码:

elif ((mirna[counter] == 'G' or mirna[counter] == 'g') and (wobblecount < 2)):
        compliment = compliment + "t"
        createonewobble(mirna, counter+1 , wobblecount+1, compliment)
        compliment = compliment + "a"
        createonewobble(mirna, counter+1 , wobblecount, compliment)

例如,假设到目前为止compliment = X,您第一次使用compliment = Xt 调用createonewobble,第二次使用compliment = Xta,我确定这不是您想要的。

一个可行的解决方案:

def create_one_wobble(options, mirna, wobble_count, compliment):

    mirna = mirna.lower()

    if wobble_count == 2:
        for letter in mirna:
            if letter == 'a':
                compliment += 't'
            elif letter == 'c':
                compliment += 'g'
            elif letter == 'g':
                compliment += 'c'
            else:
                compliment += 'a'
        options.append(compliment)

    else:
        for index, letter in enumerate(mirna):
            if letter == 'a':
                compliment += 't'
            elif letter == 'c':
                compliment += 'g'
            elif letter == 'g':
                create_one_wobble(options, mirna[index+1:], wobble_count + 1, compliment + "t")
                create_one_wobble(options, mirna[index+1:], wobble_count + 1, compliment + "c")
                compliment += 'c'
            elif letter == 'u':
                create_one_wobble(options, mirna[index+1:], wobble_count + 1, compliment + "g")
                create_one_wobble(options, mirna[index+1:], wobble_count + 1, compliment + "a")
                compliment += 'a'

permutations = []
mirna = "auugca"
create_one_wobble(permutations, mirna, 0, "")
permutations = sorted(list(set(permutations)))
for a in permutations:
    print(a)

打印出来:

taacgt
taatgt
tagcgt
tagtgt
tgacgt
tgatgt
tggcgt

编辑:

关于点数 1。 很明显(至少对我来说)你有一些编程背景,而且算法和函数的想法对你来说并不是全新的。

话虽如此,很明显你对 Python 有点陌生。

Python 应该是一种易于编写 - 易于理解的语言。 “pythonic 代码”是一段代码,编写得尽可能简单,可以利用 Python 标准库的强大功能。

  1. 了解 Python 中的类型。

    for counter in range(location, len(mirna)):
    

    这行代码使用索引来遍历字符串。在 Python 中 string 已经是 iterable 对象。这意味着你可以做 这个:

    for letter in word:
    

    假设word 是一个字符串,一切都会按计划进行。

  2. 可读性。

    if (mirna[counter] == 'A' or mirna[counter] == 'a'):
    

    这行代码用来决定mirna字符串在counter处的内容,同时处理大小写。

    我打赌你会同意我的观点

    if letter == 'a':
    

    更具可读性。因此,结合我之前的注释,您需要事先做的是mirna = mirna.lower(),这将使所有字母小写并将比较次数减少一半(这个“一半”预测并不完全正确,而是你明白了)。

  3. 使用内置机制。

    createonewobble(mirna, counter+1 , wobblecount+1, compliment)
    

    这一行将整个字符串作为一个参数加上一个数字参数传递给函数,该参数告诉函数从哪里开始。这里的最佳做法是使用slices。此机制允许您仅传递原始字符串的slice 或窗口(如果您愿意)。这样你就不需要额外的数字参数。 如果我希望对函数的下一次调用迭代从 counter+1 位置开始的字符串,我可以这样做:

    createonewobble(mirna[counter + 1:], wobblecount+1, compliment)
    

    此语法表示[from:to],当其中一个被省略时,表示从开始\一直到结束。 More on slices.

  4. Naming conventions 是您应该阅读的其他内容。

总结

还有很多,甚至是更有经验的 Python 用户每天都会学到一两件事。 我真的推荐Code Review。这是提高 Python 写作技巧的最佳场所。

【讨论】:

  • 这里快凌晨 2 点了,我刚起床喝水,看到你的回答,似乎是正确的。非常感谢。我明天早上检查一下。在那之前,如果您能详细说明您所说的关于我的逻辑/程序不是 pythonic 以及如何使我的代码更具可读性的第 1 点。再次非常感谢。我不知道 python 中的集合,但我一定会查一下。
  • 感谢您的帮助和建议。有用。我会调查你所说的事情。这段代码是一个更大的程序程序的一部分,这只是它的功能之一。完成后,我将提交我的代码以供审查。而且你也很清楚我知道一些编程但只是一些 Python 语法的事实。早上好。
  • 我完成并发布了它以供审查。请查看codereview.stackexchange.com/q/172673/146389
猜你喜欢
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多