我的 Python 代码只选择了列表内容的一半?

My Python code is only selecting half of a list's contents?

我是 Python 的新手,我正在研究我在网上找到的一些示例项目,但我目前卡在回文检查器上。

现在,我的代码将一个单词作为输入,将其分成两半,将每个部分保存到单独的变量中,制作两个变量列表,然后它应该从那里反转第二个列表,以便我可以比较它到第一个,但从我收集到的试图修复它的信息来看,它只是将一半的选择附加到新列表中。

例如,如果我输入"racecar",它会把它分成"race"和"ecar"就好了,但是当我去反转"ecar"它只给我回“['c', 'e']”。 (另外,如果我切换变量来反转前半部分,我会得到同样的错误)

我已经尝试了很长一段时间,但我没有取得任何进展,所以非常感谢您的帮助!

Ninja 编辑:如果有更简单的方法(我确定有),我很想知道,但我仍然想弄清楚我已经在代码中做错了什么有所以我可以尝试从中学习

到目前为止,这是我的代码:

print "Please enter a word you want to check is a palindrome"
input = raw_input('> ')

#Gets lengths of input
full_length = len(input)
split_length = len(input) / 2

#If word has an even length split like this
if full_length % 2 == 0:
    first_half = input[0: split_length]
    second_half = input[split_length:full_length]

#If word does not have even length split like this
else:
    first_half = input[0:split_length+1]
    second_half = input[split_length:full_length]

#Make both halves lists
first_half_list = list(first_half)
print first_half_list
second_half_list = list(second_half)
print second_half_list

# Reverse second half
rev_second_half = []


for x in second_half_list:
    current_letter = second_half_list[0]
    second_half_list.remove(second_half_list[0])
    rev_second_half.insert(0, current_letter)

print rev_second_half

"""
#Check to see if both lists are identical

#If they are identical
print "This word is a palindrome!"

#If they are not identical
print "This word is not a palindrome."
"""

这是我输入 'racecar':

时得到的输出
racecar
['r','a','c','e']
['e','c','a','r']
['c', 'e']

要反转字符串(不在位):

rev_second_half = second_half_list[::-1]

扩展: 我建议将两半保留为字符串,因为您可以将它们与:== 进行比较,并且上述反转技术也适用于字符串。

有很多不必要的工作正在进行。无需转换为列表;口译员可以为您处理这一切。无需手动反转字符串;使用切片。无需手动声明字符串中第一个和最后一个字符的索引;口译员知道他们在哪里。这是代码的固定版本;你可以 view a demo at IDE One:

input = 'racecar'

#Gets lengths of input
full_length = len(input)
split_length = len(input) / 2

#If word has an even length split like this
if full_length % 2 == 0:
    first_half = input[:split_length]
    second_half = input[split_length:]

#If word does not have even length split like this
else:
    first_half = input[:split_length+1]
    second_half = input[split_length:]

print first_half
print second_half

rev_second_half = second_half[::-1]

print rev_second_half

race
ecar
race

注意到后半部分是如何反转的,通过使用带有负迭代步骤的切片?您只需对源字符串执行一次,然后将结果与原始字符串进行比较。现在你有一个单行方法来检查一个字符串是否是回文:input == input[::-1]

关于切片语法的更多信息(您可能想查看 this question)。 input[::-1]input[0:len(input):-1] 完全相同。冒号分隔三个参数,即 start : end : step。前两个创建一个范围,其中包括 start 以及它和 end 之间的所有内容,但不包括 end 本身。不指定 startend 会导致解释器假定您分别指的是 "use 0" 和 "use len"。不指定 step 会导致假设为 1。使用负步意味着 "start at end and go backwards by magnitude of step"。

如果你想省略参数并用切片指定一个范围,你需要包括冒号,这样解释器就可以分辨出哪些参数被省略了。例如,input[-1] 将 return 输入的最后一个元素,因为没有冒号意味着您正在指定索引,而负数意味着 "go backwards from the end",因此 print input[:-1] 将产生 "raceca" 如果您的输入是 "racecar".

至于你的代码哪里出了问题,问题出在你的逆向循环上。

for x in second_half_list:
    current_letter = second_half_list[0]
    second_half_list.remove(second_half_list[0])
    rev_second_half.insert(0, current_letter)

您正在从循环访问的列表中删除项目。不要那样做,这是引起问题的好方法;这就是为什么在这种情况下您只能获得列表的一半。还有不必要的复制正在进行,尽管这不会导致不正确的结果。最后,您根本没有使用迭代变量,这肯定表明您的循环代码存在某种问题。在这里,如果您修复了列表突变但继续使用 second_half_list[0],您会将该字母重复 len(second_half_list) 次。如果你真的需要反转一个列表,你可以这样做:

for x in second_half_list:
    rev_second_half.insert(0, x)

但是如果您在迭代过程中需要某种副作用,您应该只实际迭代列表。对于 python 中的纯反转,你想要这个,它会表现得更好:

rev_second_half = [reversed(second_half_list)]

你只得到两个值的原因是你在迭代列表时改变了它——你不应该这样做,只是因为推理起来很痛苦。例如:

In [34]: nums = range(5)  # [0, 1, 2, 3, 4]

In [35]: for num in nums:
   ....:    print "num", num
   ....:    print "nums", nums
   ....:    nums.remove(nums[0])
   ....:
num 0
nums [0, 1, 2, 3, 4]
num 2
nums [1, 2, 3, 4]
num 4
nums [2, 3, 4]

注意这只循环了三次。第一次通过时,一切都很好,但是您删除了第一个元素。但是,Python 的循环逻辑认为它必须转到第二个项目——但您删除了第一个项目!那是指现在的第二项,还是事情开始时的第二项?对于 Python 的内部结构,它表示现在的第二项——这是事情开始时的第三项(即值 2)。从那里,东西只是滚雪球。

这里的教训是在迭代列表时不要改变列表。就用这里提到的其他方法来逆转吧。