我对LeetCode问题进行了不同的讨论(基本上,我们需要删除数组中给定值的所有实例,而不创建或使用另一个数组(,我遇到了这个特殊的解决方案:
def removeElement(self, nums, val):
start, end = 0, len(nums) - 1
while start <= end:
if nums[start] == val:
nums[start], nums[end], end = nums[end], nums[start], end - 1
else:
start +=1
return start
我不明白这一行发生了什么:
nums[start], nums[end], end = nums[end], nums[start], end - 1
这种逗号语法对我来说并不熟悉。我在Python文档和Stack Overflow中搜索过,了解到在Python中,用逗号分隔元素会产生一个元组,但就我而言,我不明白这里是否就是这样,因为;新创建的元组";没有被分配给任何东西(里面甚至有一个赋值语句(。除非这与元组无关,而且这里完全发生了其他事情。
我想帮助理解这句话。
nums[start], nums[end], end = nums[end], nums[start], end - 1
赋值的右侧实际上创建了一个元组。左侧立即打开元组。如果你把它分成两个任务,也许会更容易理解:
# create a tuple: (nums[end], nums[start], end - 1)
atuple = nums[end], nums[start], end - 1
# unpack the tuple into: nums[start], nums[end], end
nums[start], nums[end], end = atuple
# To make it more clear, here's an example using basic values
another_tuple = 1, 2, 3
# unpack the tuple -> a = 1, b = 2, c = 3
a, b, c = another_tuple
具有多个值的赋值实际上会在内部为右侧部分创建临时变量。然而,当使用左侧部分的索引时,必须考虑接收变量的顺序。这可能会使逻辑变得有点棘手(例如,end
索引变量的分配必须是最后一个,以便在前两个容器的索引中使用其先前的值(
一个更简单的方案可以通过给整个列表的内容分配迭代器的值来使用:
nums[:] = (n for n in nums if n != val)
这只需一行即可完成工作,而无需创建另一个列表。