Python:如何检查两个输入A和B是否是没有所有标点符号的字谜,所有大写字母都是小写字母

时间:2013-11-20 01:20:45

标签: python string loops

问题的第一部分是检查输入A和输入B是否是字谜,我可以很容易地做到。

s = input ("Word 1?")
b = sorted(s)
c = ''.join(b)
t = input("Word 2?")
a = sorted(t)
d = ''.join(b)
if d == c:
    print("Anagram!")
else:
    print("Not Anagram!")

问题是问题的第二部分 - 如果删除所有标点符号,我需要检查两个单词是否为字谜,大写字母变为小写字母,但问题是假设没有使用空格。因此,例如,(ACdB;,。Eo,。“kl)和(oadcbE,LK)是字谜。问题还要求使用循环。

s = input ("Word 1?")
s = s.lower()
for i in range (0, len(s)):
    if ord(s[i]) < 97 or ord(s[i]) >122:
        s = s.replace(s[i],  '')
b = sorted(s)
c = ''.join(b)
print(c)

目前,上述代码表示字符串索引超出范围。

2 个答案:

答案 0 :(得分:1)

这是你需要添加的循环,在psuedocode中:

s = input ("Word 1?")
s_letters = ''
for letter in s:
    if it's punctuation: skip it
    else if it's uppercase: add the lowercase version to s_letters
    else: add it to s_letters
b = sorted(s_letters)

当然,您需要为t添加相同的内容。如果您已经了解了函数,则需要将其作为函数编写,并将其调用两次,而不是通过微小的更改进行复制和粘贴。

答案 1 :(得分:0)

你的循环有三个大问题。你需要解决所有这三个问题,而不仅仅是一个问题。


首先,s = s.replace(s[i], '')不会用空格替换i个字符,而是替换i个字符和同一个字符的每个其他副本有空间。如果有任何重复,这将搞砸你的循环的其余部分。它也很慢,因为你必须一遍又一遍地搜索整个字符串。

在特定索引处替换字符的正确方法是使用切片:s = s[:i] + s[i+1:]

或者,您可以通过将字符串转换为字符列表(s = list(s))来简化此操作,您可以将其变异(del s[i])。


接下来,我们将完成循环6次,检查s[0]s[1]s[2]s[3]s[4]和{{1 }}。但在某个地方,我们将删除一些角色(理想情况下是其中的三个)。因此,其中一些索引将超过字符串的末尾,这将引发s[5]。我不会解释如何解决这个问题,因为它直接与下一个问题有关。


循环时修改序列总是会破坏循环。*想象一下从IndexError开始。让我们逐步完成循环。

  • s = '123abc',因此您检查i = 0s[0],然后将其删除,留下1
  • s = '23abc',因此您检查i = 1s[1],然后将其删除,留下3
  • s = '2abc',因此您选中了i = 2 s[2],这样就离开了b
  • 等等。

删除s = '2abc'后,2已移至s[0]。但是一旦你通过它,你永远不会回到1。所以,你永远不会检查i = 0。您可以通过几种不同的方式解决此问题 - 向后迭代,每次通过2执行while而不是if等等 - 但大多数解决方案只会加剧以前的问题。

解决这两个问题的简单方法是在循环时不修改字符串。您可以通过例如构建要删除的索引列表,然后以相反的顺序应用它来完成此操作。

但更容易实现的方法就是在你进行时建立你想要保留的角色。这也为您自动解决了第一个问题。

所以:

for

通过相对较小的更改,您的代码可以正常运行。


虽然我们正处于这种状态,但有一些方法可能会使事情过于复杂。

首先,您不需要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。这使事情更具可读性。

但是,更简单地说,您可以使用isalphaislower方法。 (因为你已经转换为s[i] < 'a',并且你一次只处理一个字符,所以它并不重要。)除了更易读,更难出错之外,这还有使用非ASCII字符的优势,例如lower

最后,你几乎不想写这样的循环:

é

这迫使你在整个地方写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) 的全部4行代码转换为这些单行中的任何一行,这些单行更易读,也更短:

new_s

事实上,整个事情可以成为一个单行:

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,使这部分变得微不足道,而不是很难),然后它就可以了。但是,除了学习规则并仔细分析您的代码以确定您是否正在使用它之前,它更容易做到这一点。