【问题标题】:String reversal only reverses half the string字符串反转只反转一半的字符串
【发布时间】:2016-01-06 04:56:07
【问题描述】:

我知道我可以只使用 reverse 函数来反转字符串,但是对于 Codecademy 作业,我试图在没有 reverse[::-1] 的情况下反转字符串。在试图找出我的代码有什么问题时,我偶然发现了问题的可能解决方案,但在这一点上,我只想了解我的代码在做什么。

def reverse(text):
    text2 = list(text)
    backwards = []
    for char in text2:
        backwards.append(text2[-1])
        del(text2[-1])
    return "".join(backwards)

text = raw_input("Say something:\n")

print reverse(text)

当我测试这个时,输出总是反转字符串的后半部分。我不明白为什么for char in text2: 会被解释为for half_the_char in text2。我的代码怎么解释这种奇怪的?

【问题讨论】:

    标签: python reverse


    【解决方案1】:

    您正在循环列表从中删除。因此,当您到达中点时,列表的 第二 半部分已经消失,for 循环停止,因为没有更多的项目可以迭代了。

    每次迭代打印出你的列表,你会看到发生了什么:

    >>> text2 = list('hello')
    >>> backwards = []
    >>> for char in text2:
    ...     backwards.append(text2[-1])
    ...     del text2[-1]
    ...     print 'char:', char, 'backwards:', backwards, 'text2:', text2
    ... 
    char: h, backwards: ['o'] text2: ['h', 'e', 'l', 'l']
    char: e, backwards: ['o', 'l'] text2: ['h', 'e', 'l']
    char: l, backwards: ['o', 'l', 'l'] text2: ['h', 'e']
    

    for 循环然后停止,因为没有更多的项目可以在左边迭代;在遍历索引012 之后,列表已经缩短到没有索引3 的程度。

    您可以改用while 循环:

    while text2:
        backwards.append(text2[-1])
        del(text2[-1])
    

    现在循环仅在 text2 完全为空时停止。

    或者你可以循环遍历text,它具有相同的长度和相同的字符;它几乎与您原来的 for 循环一样毫无意义,因为您忽略 char 循环目标完​​全相同:

    for char in text:
        backwards.append(text2[-1])
        del(text2[-1])
    

    text 至少不会在循环时缩短,因此您的迭代不会过早结束。

    或者您可以使用单独的 index 来选择要添加的字符,每次迭代都对其进行调整,然后 nottext2 中删除:

    index = -1
    for character in text2:
        backwards.append(text2[index])
        index -= 1
    

    现在您将迭代len(text2) 次。当然,你不再需要将text 转换为列表,你可以索引到text

    【讨论】:

    • 在这种情况下,'h' 和 'e' 仍然在 text2 中,所以在我看来它们仍然仍然可以转移。在所有三个显示的迭代中,这些字母共同构成“你好”。列表的前半部分仍然存在。
    • @thektulu7: 但for 循环不再迭代。它已经通过这些字符。
    • 在看到您最近的编辑后,我想我现在明白了。谢谢!
    • @thektulu7:@​​987654343@ 循环不能返回到这两个字符。列表迭代器使用索引,所以首先你得到text2[0],然后下一次迭代你得到text2[1],然后是text2[2]。但是因为你从列表中删除了元素,所以没有text2[3]anymore,所以循环停止了。
    【解决方案2】:

    del(text2[-1]) 这行说明了你的古怪。您正在设置每个字符,但是对于您踩到的每个字符,您从末尾删除一个,因此一旦您完成一半,您的字符串将一无所有。

    不要删除原始字符,而是添加您正在迭代的字符:

    for char in text2:
        backwards.insert(0, char)
    

    请参阅此问题以供参考:What's the idiomatic syntax for prepending to a short python list?

    另一种选择是向后迭代字符串并附加到列表中:

    for i in range(len(text2)):
        backwards.append(text2[-(i + 1)])
    

    【讨论】:

    • 感谢您提供替代解决方案和链接。
    【解决方案3】:

    您正在从原始列表中删除值

    del(text2[-1])
    

    让我们考虑一个示例字符串“star”,索引为 0-3。 在第一次迭代中,您将“r”添加到向后列表中,然后从原始列表中删除“r”(最后一个字符),所以现在您还剩下“sta”字符串,但您的迭代次数减少到 3。循环不断删除和减少列表大小,从而减少迭代。这会导致循环提前终止。

    【讨论】:

    • 请注意,他们删除了最后一个字符,因此删除了“r”,然后删除了“a”。从前面删除会跳过字符,从末尾删除只会提前终止for
    • 我的错。让我解决这个问题。谢谢!
    • 那么循环是否认为删除在某种程度上不仅仅是字符的删除,而是迭代的删除?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多