不使用reverse()或[:: - 1]反转字符串?

sam*_*rap 39 python string reverse for-loop function

我遇到了一个奇怪的Codecademy练习,它需要一个函数,它将一个字符串作为输入并以相反的顺序返回它.唯一的问题是你无法在stackoverflow上使用反向方法或常见答案[::-1].

显然在编程的现实世界中,人们很可能会使用扩展切片方法,甚至使用reversed函数,但也许有些情况下这不起作用?

我在Q&A风格中提出了以下解决方案,以防将来对人们有所帮助.

Ble*_*der 62

你也可以通过递归来做到这一点:

def reverse(text):
    if len(text) <= 1:
        return text

    return reverse(text[1:]) + text[0]
Run Code Online (Sandbox Code Playgroud)

这是一个简单的字符串示例hello:

   reverse(hello)
 = reverse(ello) + h           # The recursive step
 = reverse(llo) + e + h
 = reverse(lo) + l + e + h
 = reverse(o) + l + l + e + h  # Base case
 = o + l + l + e + h
 = olleh
Run Code Online (Sandbox Code Playgroud)

  • @EmanuelePaolini:`[:: - 1]`是你应该使用的唯一东西.所有这些答案只是不同的方式来反转一个字符串,没有速度保证. (4认同)
  • @ChrisPurrone:CPython根本不做任何类型的递归优化(从我记忆中).事实上,CPython甚至不优化尾递归函数,它可以很容易地转换成等效的迭代函数. (2认同)

Jon*_*nts 18

另一种选择:

from collections import deque
def reverse(iterable):
    d = deque()
    d.extendleft(iterable)
    return ''.join(d)
Run Code Online (Sandbox Code Playgroud)


sam*_*rap 11

编辑

最近关于这个问题的活动使我回顾并使用发电机将我的解决方案改为快速单线:

rev = ''.join([text[len(text) - count] for count in xrange(1,len(text)+1)])
Run Code Online (Sandbox Code Playgroud)

虽然这里有一些更好的答案,比如范围或xrange函数中的负步骤.以下是我原来的解决方案:


这是我的解决方案,我将逐步解释

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1

    lst = ''.join(lst)
    return lst

print reverse('hello')
Run Code Online (Sandbox Code Playgroud)

首先,在这种情况下,我们必须将参数传递给函数text.

接下来,我设置一个空列表,命名lst为稍后使用.(在我进入for循环之前,我实际上不知道我需要列表,你会在一秒钟内看到为什么它是必要的.)

count一旦进入for循环,变量就会有意义

那么让我们来看看我们要完成的基本版本:

将最后一个字符附加到列表将开始相反的顺序是有道理的.例如:

>>lst = []
>>word = 'foo'
>>lst.append(word[2])
>>print lst
['o']
Run Code Online (Sandbox Code Playgroud)

但是为了继续撤销订单,我们需要追加word[1]然后word[0]:

>>lst.append(word[2])
>>lst.append(word[1])
>>lst.append(word[0])
>>print lst
['o','o','f']
Run Code Online (Sandbox Code Playgroud)

这很棒,我们现在有一个列表,它的原始单词顺序相反,可以通过使用转换回字符串.join().但是有一个问题.这适用于单词foo,它甚至适用于任何长度为3个字符的单词.但是有5个字符的单词怎么样?还是10个字符?现在它不会起作用.如果我们可以动态更改我们追加的索引,以便以相反的顺序返回任何单词,该怎么办?

输入循环.

for i in range(0,len(text)):

    lst.append(text[len(text)-count])
    count += 1
Run Code Online (Sandbox Code Playgroud)

首先,有必要使用in range()而不仅仅是in因为我们需要遍历单词中的字符,但我们还需要拉出单词的索引值以便我们更改顺序.

我们的for循环体的第一部分应该看起来很熟悉.它非常相似

>>lst.append(word[..index..])
Run Code Online (Sandbox Code Playgroud)

事实上,它的基本概念完全相同:

>>lst.append(text[..index..])
Run Code Online (Sandbox Code Playgroud)

那么中间的所有东西都在做什么?

好吧,我们需要先将最后一个字母的索引附加到列表中,这是单词的长度text,-1.从现在开始,我们将其称为l(t)-1

>>lst.append(text[len(text)-1])
Run Code Online (Sandbox Code Playgroud)

lst无论单词的长度如何,仅此一项将始终得到我们单词的最后一个字母并将其追加.但是现在我们有了最后一个字母,即l(t) - 1,我们需要倒数第二个字母,即l(t) - 2,依此类推,直到没有更多字符附加到列表中.还记得count上面的变量吗?这将派上用场.通过使用for循环,我们可以在count每次迭代时将值递增1,这样我们减去的值就会增加,直到for循环迭代整个单词:

>>for i in range(0,len(text)):
..        
..      lst.append(text[len(text)-count])
..      count += 1
Run Code Online (Sandbox Code Playgroud)

现在我们已经掌握了我们的功能,让我们看看到目前为止我们所拥有的:

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1
Run Code Online (Sandbox Code Playgroud)

我们差不多完成了!现在,如果我们用"hello"这个词来调用我们的函数,我们会得到一个如下所示的列表:

[ 'O', 'L', 'L', 'E', 'H']

我们不想要一个列表,我们想要一个字符串.我们可以用.join它:

def reverse(text):

    lst = []
    count = 1

    for i in range(0,len(text)):

        lst.append(text[len(text)-count])
        count += 1

    lst = ''.join(lst) # join the letters together without a space
    return lst
Run Code Online (Sandbox Code Playgroud)

就是这样.如果我们在reverse()上调用'hello'这个词,我们就会得到:

>>print reverse('hello')
olleh
Run Code Online (Sandbox Code Playgroud)

显然,这是在现实生活中需要的代码.使用反转函数或扩展切片将是完成此任务的最佳方法,但也许有一些实例,当它不起作用,你需要这个.无论哪种方式,我想我会分享给任何有兴趣的人.

如果你们有任何其他想法,我很乐意听到他们!


Ash*_*ary 11

使用逆转range:

def reverse(strs):
    for i in xrange(len(strs)-1, -1, -1):
        yield strs[i]
...         
>>> ''.join(reverse('hello'))
'olleh'
Run Code Online (Sandbox Code Playgroud)

xrange或者 range使用-1步骤将以相反的顺序返回项目,因此我们需要迭代len(string)-1-1(独占)并逐个从字符串中获取项目.

>>> list(xrange(len(strs) -1, -1 , -1))
[4, 3, 2, 1, 0]  #iterate over these indexes and fetch the items from the string
Run Code Online (Sandbox Code Playgroud)

一内胆:

def reverse(strs):
    return ''.join([strs[i] for i in xrange(len(strs)-1, -1, -1)])
... 
>>> reverse('hello')
'olleh'
Run Code Online (Sandbox Code Playgroud)

  • 这是过早优化的情况. (2认同)

小智 7

只编写Python几天,但我觉得这是一个相当干净的解决方案.创建一个空列表,遍历字符串中的每个字母并将其附加到列表的前面,将连接列表作为字符串返回.

def reverse(text):
backwardstext = []
for letter in text:
    backwardstext.insert(0, letter)
return ''.join(backwardstext)
Run Code Online (Sandbox Code Playgroud)


Sum*_*aha 5

我用过这个:

def reverse(text):
s=""
l=len(text)
for i in range(l):
    s+=text[l-1-i]
return s
Run Code Online (Sandbox Code Playgroud)