如何使用列表解析从列表中间丢弃元素?
我本来可以用索引来做到这一点,但我觉得应该有更简单的方法,能用列表推导式来实现。我是个初学者,希望这个方法不是太明显。谢谢!
for x in firstList:
firstFunc(x)
secondFunc(x)
x = process(x)
if x.discard == True:
(get rid of x)
secondList.append(firstList)
6 个回答
几点说明:
- 你不能用
append
来添加列表的内容,应该用extend
。 - 没有必要写
== True
这种形式,直接用if x.discard:
就可以了。 - 最好是创建一个新列表,里面放你不想丢弃的值,这样就不会在循环中搞得一团糟。
所以你可以这样做:
tmp = []
for x in first_list:
x = process(x)
if not x.discard:
tmp.append(x)
second_list.extend(tmp)
当然,用列表推导式会更符合 Python 的风格:
[i for i in first_list if not process(i).discard]
只是随便想想,这对文档帮助不大,但为什么不试试呢:
def masterFunc(x):
firstFunc(x)
secondFunc(x)
process(x)
return x.discard
secondList = [ x for x in firstList if masterFunc(x) ]
好消息:严格来说,它完成了你要求的功能。
坏消息:它把firstFunc、secondFunc和process给隐藏起来了。
听起来你在这个例子中已经遇到了副作用和命令/查询分离的问题,所以我觉得这个小技巧并没有想象中那么好,可能只是稍微清理一下代码而已。你可能会发现,有些方法需要反转(比如用x.firstFunc()而不是firstFunc(x)),还有些方法需要拆分开来。也许还有比'x.discard'更好的方式来处理过滤。
你知道吗,其实最好的办法就是按照你喜欢的方式初始化 secondList,然后在一个普通的循环里执行这三个函数,因为它们之间是有依赖关系的,而且每个函数的逻辑不仅仅是过滤(你提到的处理设置属性……我猜你的意思是除了丢弃之外的其他操作):
# If secondList not initialized...
secondList = []
for x in firstList:
firstFunc(x)
secondFunc(x)
process(x)
if not x.discard:
secondList.append(x)
在这里,列表推导式帮助不大,因为你在每个函数里都在处理数据(不过它们确实可以减少一两行代码;这要看你对“干净”代码的定义)。如果 process() 只是判断某个项目是否应该在新列表里,返回 True 或 False,那下面的写法在我看来会更好。
如果 firstFunc(x) 和 secondFunc(x) 在 process() 之后确实改变了 x.discard 的结果,而 process(x) 的结果就是 x,那么在你的情况下我会这样做:
for x in firstList:
firstFunc(x)
secondFunc(x)
secondList = [ x for x in firstList if not process(x).discard ]
不过,如果 process(x) 的结果和 x 不一样,就像你的示例所显示的那样,你也可以把最后一行改成这样:
interimList = [ process(x) for x in firstList ]
secondList = [ x for x in interimList if not x.discard ]
注意,如果你想把这些结果添加到 secondList 中,可以使用 secondList.extend([...])。
补充:我意识到我错误地写了“do not”改变,但我想说的是如果它们确实改变了 process() 的结果。
补充 2:清理描述和代码。