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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18686860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:27:45  来源:igfitidea点击:

Reverse a string without using reversed() or [::-1]?

pythonstringfunctionfor-loopreverse

提问by samrap

I came across a strange Codecademy exercise that required a function that would take a string as input and return it in reverse order. The only problem was you could not use the reversed method or the common answer here on stackoverflow, [::-1].

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

Obviously in the real world of programming, one would most likely go with the extended slicemethod, or even using the reversedfunction but perhaps there is some case where this would not work?

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

I present a solution below in Q&A style, in case it is helpful for people in the future.

我在下面以问答方式提出了一个解决方案,以防将来对人们有所帮助。

回答by samrap

EDIT

编辑

Recent activity on this question caused me to look back and change my solution to a quick one-liner using a generator:

最近关于这个问题的活动使我回顾并使用生成器将我的解决方案更改为快速单行:

rev = ''.join([text[len(text) - count] for count in xrange(1,len(text)+1)])

Although obviously there are some better answers here like a negative step in the range or xrange function. The following is my original solution:

尽管显然这里有一些更好的答案,例如 range 或 xrange 函数中的负步。以下是我的原始解决方案:



Here is my solution, I'll explain it step by step

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

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')

First, we have to pass a parameter to the function, in this case text.

首先,我们必须向函数传递一个参数,在本例中为text

Next, I set an empty list, named lstto use later. (I actually didn't know I'd need the list until I got to the forloop, you'll see why it's necessary in a second.)

接下来,我设置了一个空列表,命名lst为稍后使用。(在进入for循环之前,我实际上不知道我需要该列表,您马上就会明白为什么它是必要的。)

The countvariable will make sense once I get into the forloop

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

So let's take a look at a basic version of what we are trying to accomplish:

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

It makes sense that appending the last character to the list would start the reverse order. For example:

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

>>lst = []
>>word = 'foo'
>>lst.append(word[2])
>>print lst
['o']

But in order to continue reversing the order, we need to then append word[1]and then word[0]:

但是为了继续颠倒顺序,我们需要添加word[1]然后word[0]

>>lst.append(word[2])
>>lst.append(word[1])
>>lst.append(word[0])
>>print lst
['o','o','f']

This is great, we now have a list that has our original word in reverse order and it can be converted back into a string by using .join(). But there's a problem. This works for the word foo, it even works for any word that has a length of 3 characters. But what about a word with 5 characters? Or 10 characters? Now it won't work. What if there was a way we could dynamically change the index we append so that any word will be returned in reverse order?

太好了,我们现在有一个列表,其中的原始单词以相反的顺序排列,并且可以使用 将其转换回字符串.join()。但是有一个问题。这适用于单词 foo,它甚至适用于任何长度为 3 个字符的单词。但是一个有 5 个字符的单词呢?还是10个字符?现在行不通了。如果有一种方法可以动态更改我们附加的索引,以便任何单词都以相反的顺序返回,该怎么办?

Enter for loop.

进入 for 循环。

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

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

First off, it is necessary to use in range()rather than just in, because we need to iterate through the characters in the word, but we also need to pull the index value of the word so that we change the order.

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

The first part of the body of our for loop should look familiar. Its very similar to

for 循环体的第一部分应该看起来很熟悉。它非常类似于

>>lst.append(word[..index..])

In fact, the base concept of it is exactly the same:

事实上,它的基本概念是完全一样的:

>>lst.append(text[..index..])

So what's all the stuff in the middle doing?

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

Well, we need to first append the index of the last letter to our list, which is the length of the word, text, -1. From now on we'll refer to it as l(t) -1

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

>>lst.append(text[len(text)-1])

That alone will always get the last letter of our word, and append it to lst, regardless of the length of the word. But now that we have the last letter, which is l(t) - 1, we need the second to last letter, which is l(t) - 2, and so on, until there are no more characters to append to the list. Remember our countvariable from above? That will come in handy. By using a forloop, we can increment the value of countby 1 through each iteration, so that the value we subtract by increases, until the for loop has iterated through the entire word:

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

Now that we have the heart of our function, let's look at what we have so far:

现在我们有了函数的核心,让我们看看到目前为止我们有什么:

def reverse(text):

    lst = []
    count = 1

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

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

We're almost done! Right now, if we were to call our function with the word 'hello', we would get a list that looks like:

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

['o','l','l','e','h']

['o','l','l','e','h']

We don't want a list, we want a string. We can use .joinfor that:

我们不想要一个列表,我们想要一个字符串。我们可以使用.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

And that's it. If we call the word 'hello' on reverse(), we'd get this:

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

>>print reverse('hello')
olleh

Obviously, this is way more code than is necessary in a real life situation. Using the reversed function or extended slice would be the optimal way to accomplish this task, but maybe there is some instance when it would not work, and you would need this. Either way, I figured I'd share it for anyone who would be interested.

显然,这比现实生活中需要的代码多得多。使用反向函数或扩展切片将是完成此任务的最佳方式,但也许在某些情况下它不起作用,您将需要它。不管怎样,我想我会把它分享给任何感兴趣的人。

If you guys have any other ideas, I'd love to hear them!

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

回答by Blender

You can also do it with recursion:

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

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

    return reverse(text[1:]) + text[0]

And a simple example for the string hello:

还有一个简单的字符串示例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

回答by Ashwini Chaudhary

Use reversed range:

反向使用range

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

xrangeor rangewith -1 step would return items in reversed order, so we need to iterate from len(string)-1to -1(exclusive) and fetch items from the string one by one.

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

One-liner:

单线:

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

回答by rlms

A golfed version: r=lambda x:"".join(x[i] for i in range(len(x-1),-1,-1)).

高尔夫版本:r=lambda x:"".join(x[i] for i in range(len(x-1),-1,-1)).

回答by Jon Clements

Just another option:

只是另一种选择:

from collections import deque
def reverse(iterable):
    d = deque()
    d.extendleft(iterable)
    return ''.join(d)

回答by Burhan Khalid

Inspired by Jon's answer, how about this one

受乔恩回答的启发,这个怎么样

word = 'hello'
q = deque(word)
''.join(q.pop() for _ in range(len(word)))

回答by CT Zhu

This is a very interesting question, I will like to offer a simple one liner answer:

这是一个非常有趣的问题,我想提供一个简单的单行答案:

>>> S='abcdefg'
>>> ''.join(item[1] for item in sorted(enumerate(S), reverse=True))
'gfedcba'

Brief explanation:

简要说明:

enumerate()returns [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]. The indices and the values. To reverse the values, just reverse sort it by sorted(). Finally, just put it together back to a str

enumerate()返回[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g')]。指数和值。要反转值,只需按 反转排序即可sorted()。最后,只需将它组合回一个str

回答by berdario

Today I was asked this same exercise on pen&paper, so I come up with this function for lists:

今天我被问到关于笔和纸的同样的练习,所以我想出了这个列表函数:

def rev(s):
  l = len(s)
  for i,j in zip(range(l-1, 0, -1), range(l//2)):
    s[i], s[j] = s[j], s[i]
  return s

which can be used with strings with "".join(rev(list("hello")))

可以与字符串一起使用 "".join(rev(list("hello")))

回答by rajpython

you have got enough answer.

你有足够的答案。

Just want to share another way.

只是想分享另一种方式。

you can write a two small function for reverse and compare the function output with the given string

您可以为 reverse 编写一个两个小函数,并将函数输出与给定的字符串进行比较

var = ''

变量 = ''

def reverse(data):

定义反向(数据):

for i in data:
    var = i + var
return var

if not var == data :

如果不是 var == 数据:

print "No palindrome"

打印“没有回文”

else :

别的 :

print "Palindrome"

打印“回文”

回答by dewetha

i just solved this in code academy and was checking my answers and ran across this list. so with a very limited understanding of python i just did this and it seamed to work.

我刚刚在代码学院解决了这个问题,正在检查我的答案并浏览了这个列表。因此,由于对 python 的了解非常有限,我只是这样做了,并且它确实可以工作。

def reverse(s):
    i = len(s) - 1
    sNew = ''
    while  i >= 0:
        sNew = sNew + str(s[i])
        i = i -1
    return sNew