目录
1. 列表推导式简介
列表推导式(List Comprehension)是一种简洁而强大的方式用于创建新的列表。它允许你使用一种紧凑的语法来从一个现有的可迭代对象(如列表、字符串等)中创建新的列表。
列表推导式的基本语法如下所示:
new_list = [expression for item in iterable if condition]
其中:
new_list
是生成的新列表。expression
是对每个item
执行的表达式或操作,用于生成新的列表元素。item
是可迭代对象中的每个元素。iterable
是一个可迭代对象,如列表、字符串等。if condition
(可选)是一个条件表达式,用于筛选出满足条件的元素。
我们举一个简单的例子,这个例子演示了如何使用列表推导式将列表里的元素翻倍:
numbers = [1, 2, 3, 4, 5]
doubled_numbers = [num * 2 for num in numbers]
print(doubled_numbers)
在上面的例子中,我们使用列表推导式 [num * 2 for num in numbers] 将 numbers 列表中的每个元素翻倍,并将结果存储在 doubled_numbers 列表中。
列表推导式还可以包含条件语句,用于筛选满足特定条件的元素。例如,我们可以使用条件语句来过滤出偶数:
numbers = [1, 2, 3, 4, 5]
even_numbers = [num for num in numbers if num % 2 == 0]
print(even_numbers)
2. 列表推导式与for循环的区别与联系
了解完了列表推导式,我们进入正题。在Leetcode刷题过程中,我刷到了这样一道题,题目描述如下:
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
示例: 输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度5, 并且 nums 中的前五个元素为0,1,3,0,4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
一开始我给出的解答如下:
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
self.nums = nums
self.val = val
for i in self.nums:
if i == self.val:
self.nums.remove(i)
return self.nums
nums = [0,1,2,2,3,0,4,2]
val = 2
remove = Solution()
a = remove.removeElement(nums,val)
print(a)
print(len(a))
可是运行程序并不能得到想要的结果,代码执行错误,之后我将for循环替换成了相应功能的列表推导式 ,修改代码如下:
class Solution(object):
def removeElement(self, nums, val):
"""
:type nums: List[int]
:type val: int
:rtype: int
"""
self.nums = nums
self.val = val
self.nums = [num for num in self.nums if num != self.val]
return self.nums
nums = [0, 1, 2, 2, 3, 0, 4, 2]
val = 2
remove = Solution()
result = remove.removeElement(nums, val)
print(result)
此时程序运行正确。我检查了代码的逻辑应该是没有问题的,那究竟是哪里出了问题呢?经过反复检查,我发现问题出在这里:
在循环遍历self.nums的过程中,使用self.nums.remove(i)从列表中删除元素会导致迭代过程出现问题。当删除元素后,列表的长度发生变化,迭代器会失效,可能会导致跳过某些元素或产生意外行为。但是列表推导式中的for循环却不会改变原有列表,而会创建新的列表;而for循环是在原有列表的基础上对原有列表进行修改。
3. 总结
1.使用列表推导式可以在一行代码中完成操作,并且会创建一个新的列表。这意味着在代码执行过程中,你会操作两个列表:原始的self.nums和生成的新列表。这可能会在处理大型列表时占用更多的内存。(具体来说,这段代码使用列表推导式来创建一个新的列表,其中排除了与self.val相等的元素。原始列表的元素不会直接被修改,而是根据筛选条件创建一个新的列表。新列表可以选择使用与原始列表相同的名称,但这样做会使代码难以理解和维护。)
2.使用循环和条件语句的方式直接在原始列表上进行操作,不会创建新的列表。这样可以避免创建新的列表对象,但在循环过程中直接修改列表可能会导致意外的结果。在循环过程中修改正在迭代的列表可能会导致索引错误或意外的行为。为了避免这种情况,可以考虑使用另一个临时列表来存储需要删除的元素,然后在循环结束后一次性移除它们。