每次出现元音时反转字符串的函数?
function that reverses a string every time a vowel appears in it?
我正在尝试制作一个函数,对于字符串中每次出现的元音,反转所述字符串(并在执行此操作时包括元音)。就我的理解而言,该功能有些复杂,因此我需要一些帮助并可能对其进行细分。但是,我只想使用我目前正在学习的运算符和语句(for/while 和 if)。如果可能的话,我也想避免使用列表理解。
输入和输出应该是这样的:
示例输入是 reverse_per_vowel('aerith')
其中 returns 'iraeth'
如果我们把这个函数的过程分解成几个步骤,它应该是这样的:
(a)erith → (a)erith (第一个字母是元音,所以是相反。但是,因为它是字符串中的第一个字母,所以没有可见的变化。)
(ae)rith → (ea)rith (第二个字母也是元音,所以字符串中元音之前和包括元音的每个字母都被颠倒了。)
(eari)th → (irae)th (第四个字母是元音,所以导致并包括它的所有内容也被反转。请注意它如何解释字符串中先前被反转的字母。)
如您所见,字符串反转的次数是累积的,我不太确定如何对此进行编码。但是,我尝试编写该函数的一个组件。
我正在尝试什么
vowellist = 'aeiouAEIOU'
sampleword = 'aerith'
indexlist = []
for i in range(len(sampleword)):
if sampleword[i] in vowel_list:
indexlist.append(i)
indexlist
输出:[0, 1, 3]
此摘录不会反转字符串的任何部分,但它 returns 索引了字符串应反转的位置。我计划做的是以某种方式将这些索引插入到示例单词中,并使用 [::-1] 来反转字符串的一部分。但是,我不知道该怎么做,也不知道这是否是个好主意。任何帮助将不胜感激。
实现此目的的一种简单方法是使用递归:
vowels = set('aeiouAEIOU')
def reverse_per_vowel(s):
if not s: # empty string
return ''
beforelast, last = s[:-1], s[-1]
if last in vowels:
return last + reverse_per_vowel(beforelast)[::-1]
return reverse_per_vowel(beforelast) + last
print(reverse_per_vowel('aerith')) # iraeth
您可以通过简单修改 for
循环和一些高级切片来实现:
vowellist = 'aeiouAEIOU'
sampleword = 'aerith'
for i in range(len(sampleword)):
if sampleword[i] in vowellist:
sampleword = sampleword[i::-1] + sampleword[i + 1:]
print(sampleword)
每次迭代,如果元音出现,您可以重新分配新的部分反转的字符串。
输出:
iraeth
你可以帮助我的国家,检查my profile info。
如果有很多元音,那么重复的反转似乎是可以避免的,因为第二次反转在某种程度上是对前一次反转的撤销。
是的,你可以使用这个算法:
构建两个字符串。它们开始为空,并将其中第二个标记为“活动”。
以相反的顺序访问输入字符:从最后到第一个
- 只要是辅音就加到当前激活的字符串中
- 当它是元音时,将活动字符串切换为另一个,并在那里添加元音
在此过程结束时,反转第二个字符串和return两个字符串的连接:
VOWELS = set("aeiouAEIOU")
def reverse_per_vowel(s):
endings = ["", ""]
side = 1
for c in reversed(s):
if c in VOWELS:
side = 1 - side # Toggle between 0 and 1
endings[side] += c
return endings[0] + endings[1][::-1]
由于该算法不会在每次遇到元音时都反转,而是在最后只执行一次反转,因此它以线性时间复杂度运行,这与您按字面意义实现所描述的过程会得到的结果相反,它具有O(n²) 的最坏情况时间复杂度。
通过这种复杂性分析,我假设用字符扩展字符串是一个常数时间过程。如果对此有疑问,则用两个字符列表实现它,调用append
并在过程结束时执行join
以获得最终字符串:
VOWELS = set("aeiouAEIOU")
def reverse_per_vowel(s):
endings = [[], []]
side = 1
for c in reversed(s):
if c in VOWELS:
side = 1 - side # Toggle between 0 and 1
endings[side].append(c)
return "".join(endings[0] + endings[1][::-1])
使用列表使它变得非常简单和干净:
def reverse_per_vowel(word):
result = []
for letter in word:
result.append(letter)
if letter in 'aeiouAEIOU':
result.reverse()
return ''.join(result)
速度也很快。对于你的示例单词,它比目前发布的所有其他解决方案都快,对于一个有 1000 个字母的单词 ('aerith' * 167
),只有 @trincot 的第二个解决方案快一点,其他的慢 2 到 10 倍.当然最终它真的输给了 trincot 的第二个解决方案,它在 10,000 个字母时快了大约 5 倍,在 100,000 个字母时快了大约 46 倍。
这是另一个 linear-time,比 trincot 的快一点(在包含多达一百万个字母的字符串上测试)。它将字母放入一个双端队列中,因此它可以有效地附加到左侧或右侧。并且它有一个标志,告诉当前结果是否是反向的。
from collections import deque
def reverse_per_vowel(word):
result = deque()
reverse = False
for letter in word:
if not reverse:
result.append(letter)
else:
result.appendleft(letter)
if letter in 'aeiouAEIOU':
reverse = not reverse
if reverse:
result.reverse()
return ''.join(result)
我正在尝试制作一个函数,对于字符串中每次出现的元音,反转所述字符串(并在执行此操作时包括元音)。就我的理解而言,该功能有些复杂,因此我需要一些帮助并可能对其进行细分。但是,我只想使用我目前正在学习的运算符和语句(for/while 和 if)。如果可能的话,我也想避免使用列表理解。
输入和输出应该是这样的:
示例输入是 reverse_per_vowel('aerith')
其中 returns 'iraeth'
如果我们把这个函数的过程分解成几个步骤,它应该是这样的:
(a)erith → (a)erith (第一个字母是元音,所以是相反。但是,因为它是字符串中的第一个字母,所以没有可见的变化。)
(ae)rith → (ea)rith (第二个字母也是元音,所以字符串中元音之前和包括元音的每个字母都被颠倒了。)
(eari)th → (irae)th (第四个字母是元音,所以导致并包括它的所有内容也被反转。请注意它如何解释字符串中先前被反转的字母。)
如您所见,字符串反转的次数是累积的,我不太确定如何对此进行编码。但是,我尝试编写该函数的一个组件。
我正在尝试什么
vowellist = 'aeiouAEIOU'
sampleword = 'aerith'
indexlist = []
for i in range(len(sampleword)):
if sampleword[i] in vowel_list:
indexlist.append(i)
indexlist
输出:[0, 1, 3]
此摘录不会反转字符串的任何部分,但它 returns 索引了字符串应反转的位置。我计划做的是以某种方式将这些索引插入到示例单词中,并使用 [::-1] 来反转字符串的一部分。但是,我不知道该怎么做,也不知道这是否是个好主意。任何帮助将不胜感激。
实现此目的的一种简单方法是使用递归:
vowels = set('aeiouAEIOU')
def reverse_per_vowel(s):
if not s: # empty string
return ''
beforelast, last = s[:-1], s[-1]
if last in vowels:
return last + reverse_per_vowel(beforelast)[::-1]
return reverse_per_vowel(beforelast) + last
print(reverse_per_vowel('aerith')) # iraeth
您可以通过简单修改 for
循环和一些高级切片来实现:
vowellist = 'aeiouAEIOU'
sampleword = 'aerith'
for i in range(len(sampleword)):
if sampleword[i] in vowellist:
sampleword = sampleword[i::-1] + sampleword[i + 1:]
print(sampleword)
每次迭代,如果元音出现,您可以重新分配新的部分反转的字符串。 输出:
iraeth
你可以帮助我的国家,检查my profile info。
如果有很多元音,那么重复的反转似乎是可以避免的,因为第二次反转在某种程度上是对前一次反转的撤销。
是的,你可以使用这个算法:
构建两个字符串。它们开始为空,并将其中第二个标记为“活动”。
以相反的顺序访问输入字符:从最后到第一个
- 只要是辅音就加到当前激活的字符串中
- 当它是元音时,将活动字符串切换为另一个,并在那里添加元音
在此过程结束时,反转第二个字符串和return两个字符串的连接:
VOWELS = set("aeiouAEIOU")
def reverse_per_vowel(s):
endings = ["", ""]
side = 1
for c in reversed(s):
if c in VOWELS:
side = 1 - side # Toggle between 0 and 1
endings[side] += c
return endings[0] + endings[1][::-1]
由于该算法不会在每次遇到元音时都反转,而是在最后只执行一次反转,因此它以线性时间复杂度运行,这与您按字面意义实现所描述的过程会得到的结果相反,它具有O(n²) 的最坏情况时间复杂度。
通过这种复杂性分析,我假设用字符扩展字符串是一个常数时间过程。如果对此有疑问,则用两个字符列表实现它,调用append
并在过程结束时执行join
以获得最终字符串:
VOWELS = set("aeiouAEIOU")
def reverse_per_vowel(s):
endings = [[], []]
side = 1
for c in reversed(s):
if c in VOWELS:
side = 1 - side # Toggle between 0 and 1
endings[side].append(c)
return "".join(endings[0] + endings[1][::-1])
使用列表使它变得非常简单和干净:
def reverse_per_vowel(word):
result = []
for letter in word:
result.append(letter)
if letter in 'aeiouAEIOU':
result.reverse()
return ''.join(result)
速度也很快。对于你的示例单词,它比目前发布的所有其他解决方案都快,对于一个有 1000 个字母的单词 ('aerith' * 167
),只有 @trincot 的第二个解决方案快一点,其他的慢 2 到 10 倍.当然最终它真的输给了 trincot 的第二个解决方案,它在 10,000 个字母时快了大约 5 倍,在 100,000 个字母时快了大约 46 倍。
这是另一个 linear-time,比 trincot 的快一点(在包含多达一百万个字母的字符串上测试)。它将字母放入一个双端队列中,因此它可以有效地附加到左侧或右侧。并且它有一个标志,告诉当前结果是否是反向的。
from collections import deque
def reverse_per_vowel(word):
result = deque()
reverse = False
for letter in word:
if not reverse:
result.append(letter)
else:
result.appendleft(letter)
if letter in 'aeiouAEIOU':
reverse = not reverse
if reverse:
result.reverse()
return ''.join(result)