Python中列表推导式中的多重If/else

6
我有这个。
s = ['son','abc','pro','bro']
b = ['son','bro']
c = ['pro','quo']

预期输出如下。如果输出中的项在列表b中,则为index(item_in_s)。如果该项在c中,则为index(item_in_s)+10
[0,12,3]

我尝试了这个:
index_list = [s.index(item) if item in b else s.index(item)+10 if item in c for item in s]
print(index)

但显然这是一个语法错误。所以我尝试了这个:
index_list = [s.index(item) if item in b else s.index(item)+10 for item in s if item in c]
    print(index)

输出:

[12]

这会改变整个逻辑。虽然我可以这样做。
fin = [s.index(item) if item in b else s.index(item)+10 if item in c  else '' for item in s]
fin = [item for item in fin if item!='']
print(fin)

期望的输出已获得:
[0, 12, 3]

但是我如何在列表推导中获得我想要的东西,或者列表推导中是否有类似于 else continue 这样的语法?

我不太明白你在这里尝试做什么。 - Sam
简单来说,像 [x if x in list1 else x+10 if x in list2 for x in my_list] 这样的代码会导致语法错误。 - void
我想要类似于[x if x in list1 else x+10 if x in list2 else pass for x in my_list]这样的东西,但我知道pass也会导致语法错误。有什么替代方案吗? - void
将您的代码拆分成几行。我不理解您要输出什么与输入相关的内容。 - Sam
1
只需编写一个for循环,使用enumerate代替.index,这可以使您的算法更有效率。 - juanpa.arrivillaga
哦,谢谢你的提示。我一开始使用了enumerate,但我认为那样会很低效。你是对的,它会每次都进行搜索。 - void
4个回答

12
从根本上说,列表推导式会迫使你变得非常低效。
>>> [i if item in b else i + 10 if item in c else None for i, item in enumerate(s) if item in b or item in c]
[0, 12, 3]

这个必须在最坏情况下检查成员`item`在`b`和`c`中各两次,如果你想要那个输出的话。相反,只需使用一个for循环
>>> index_list = []
>>> for i, item in enumerate(s):
...     if item in b:
...         index_list.append(i)
...     elif item in c:
...         index_list.append(i + 10)
...
>>> index_list
[0, 12, 3]
>>>

简单、易读、直接和Python风格。
编辑
你可以通过赋值表达式实现类似的功能。
[
    i if item_in_b else i + 10 if item_in_c else None 
    for i, item in enumerate(s) 
    if (item_in_b:=item in b) or (item_in_c:=item in c)
]

但我仍然更喜欢循环。

当Python 3.8到来时,我们可以使用(item_in_b:= item in b)并稍后进行if item_in_b,从而消除条件item in b并仅检查一次。 - GeeTransit

1
你的解决方案故障可以通过避免列表b&c中不存在的元素来解决。
你可以通过创建新列表并应用简单的集合操作来实现这一点。
检查一下你的解决方案中的这个小变化。
fin = [s.index(item) if item in b else s.index(item)+10 if item in c  else '' for item in list(set(b+c)&set(s))]

通过这样做,您的条件语句中的else部分永远不会执行,因为您正在迭代的列表中只有元素是bc中的一个。

1

已经有很好的答案了,这里提供一个尚未提到的:

fin = [item for item in ([s.index(item) if item in b else s.index(item)+10 if item in c  else '' for item in s]) if item!='']
print(fin)

基本上,它是原始两行代码的组合:
fin = [s.index(item) if item in b else s.index(item)+10 if item in c  else '' for item in s]
fin = [item for item in fin if item!='']

并不一定是“更快或更好”,只是一个之前没有的组合。 在使用列表推导时,您总是有超出实际需要迭代的风险。 另一个答案中提供了更好的解决方案,即使用for循环。

如果您能解释一下您的解决方案是如何工作的,以及它为什么比其他答案更好,那将会更有用。仅有代码的答案并没有太大帮助。 - SiHa

1
index_list = [s.index(item) if item in b else s.index(item) + 10 for item in s if item in b or item in c]

我们确保它是 b 或者 c 中的一个,然后索引将是其中的一个情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接