您的循环存在三个大问题。您需要解决所有这三个问题,而不仅仅是一个。
首先,s = s.replace(s[i], '') 不会将ith 字符替换为空格,而是将ith 字符以及同一字符的所有其他副本替换为空格。如果有任何重复,那将搞砸循环的其余部分。它也很慢,因为你必须一遍又一遍地搜索整个字符串。
在特定索引处替换字符的正确方法是使用切片:s = s[:i] + s[i+1:]。
或者,您可以通过将字符串转换为字符列表 (s = list(s)) 来简化此操作,也可以就地对其进行变异 (del s[i])。
接下来,我们将循环 6 次,检查 s[0]、s[1]、s[2]、s[3]、s[4] 和 s[5]。但在此过程中,我们将删除一些字符(最好是三个)。因此,其中一些索引将超出字符串的末尾,这将引发IndexError。我不会解释如何解决这个问题,因为它直接关系到下一个问题。
在循环时修改序列总是会中断循环。* 想象一下从 s = '123abc' 开始。让我们逐步完成循环。
-
i = 0,所以你检查s[0],这是1,所以你删除它,留下s = '23abc'。
-
i = 1,所以你检查s[1],它是3,所以你删除它,留下s = '2abc'。
-
i = 2,所以你检查s[2],这是b,所以你离开它,离开s = '2abc'。
- 等等。
通过删除 1,2 移至 s[0]。但是一旦你通过了i = 0,你就再也不会回来了。所以,你永远不会去检查2。您可以通过几种不同的方式来解决这个问题——向后迭代,每次通过for 执行if 而不是if,等等——但大多数这些解决方案只会加剧之前的问题。
解决这两个问题的简单方法是在循环时不要修改字符串。你可以这样做,例如,建立一个索引列表以在你进行时删除,然后以相反的顺序应用它。
但更简单的方法是在进行过程中建立您想要保留的角色。这也自动为您解决了第一个问题。
所以:
new_s = []
for i in range (0, len(s)):
if ord(s[i]) < 97 or ord(s[i]) >122:
pass
else:
new_s.append(s[i])
b = sorted(new_s)
通过相对较小的更改,您的代码可以正常工作。
虽然我们这样做了,但有几种方法会使事情变得过于复杂。
首先,你不需要做ord(s[i]) < 97;你可以做s[i] < 'a'。这使事情更具可读性。
但是,更简单的是,您可以只使用isalpha 或islower 方法。 (由于您已经转换为lower,并且您一次只处理一个字符,这并不重要。)除了更具可读性和更难出错之外,这还具有以下优点:使用非 ASCII 字符,例如 é。
最后,你几乎不想写这样的循环:
for i in range(len(s)):
这迫使你在所有地方都写s[i],而你本来可以循环遍历s:
for ch in s:
所以,把它们放在一起,这是你的代码,有两个简单的修复和清理:
s = input ("Word 1?")
s = s.lower()
new_s = []
for ch in s:
if ch.isalpha():
new_s.append(ch)
b = sorted(new_s)
c = ''.join(b)
print(c)
如果您了解推导式或高阶函数,您就会认识到这种模式正是列表推导式的作用。因此,您可以将构建 new_s 的全部 4 行代码转换为这些单行代码中的任何一个,它们更具可读性并且更短:
new_s = (ch for ch in s if ch.isalpha)
new_s = filter(str.isalpha, s)
而事实上,整个事情都可以变成一条线:
b = sorted(ch for ch in s.lower() if ch.isalpha)
但是你的老师让你使用for 声明,所以你最好保留为for 声明。
* 这并不完全正确。如果您仅在当前索引之后修改序列的一部分,并且确保在到达每个索引时序列距离具有正确的长度,即使它之前可能具有不同的长度你做了(使用while循环而不是for循环,每次重新评估len(seq),使这部分变得微不足道而不是困难),然后它就可以工作了。但是,永远不要这样做比学习规则并仔细分析您的代码以查看您这次是否能够逃脱它更容易。