Python将两个列表与条件相交

Python将两个列表与条件相交,python,list-comprehension,Python,List Comprehension,只有在满足特定条件的情况下,这一行是合并(相交)两个列表的最佳方式(无错误且最有效)吗 res = [val for val in list_1 if val in list_2 and condition[val] == True] 即 应该返回res=[28]。字典条件始终与列表_1中的元素具有相同的键 如果我有两个集合而不是两个列表,我应该如何更改代码 最后,请注意,这是一个非常简化的案例,我为一个更大的示例生成了这个案例,但我无法直观地进行检查。我想确保我的解决方案在总体上是有效的,而

只有在满足特定条件的情况下,这一行是合并(相交)两个列表的最佳方式(无错误且最有效)吗

res = [val for val in list_1 if val in list_2 and condition[val] == True]

应该返回
res=[28]
。字典
条件
始终与
列表_1
中的元素具有相同的键

如果我有两个集合而不是两个列表,我应该如何更改代码


最后,请注意,这是一个非常简化的案例,我为一个更大的示例生成了这个案例,但我无法直观地进行检查。我想确保我的解决方案在总体上是有效的,而不仅仅是针对发布的示例。

您可以使用内置的方法设置。 这在Python的当前稳定版本—Python2.7和Python3.4中都是兼容的

list_1 = [2 4 6 8 10]
list_2 = [1 2 3 4 5 8 9]
condition = {2:True, 4:False, 6:False, 8:True, 10:True}

true_values = [x for x in condition.keys() if condition[x]] #Obtains keys having only 'True' value.

print set(list_1) & set(list_2) & set(true_values) #Give unique common value from these three lists.
如果您想让集合按升序排列,可以使用“排序”函数将最后一行替换为

print sorted(set(list_1) & set(list_2) & set(true_values)) #Will give [2, 8]

这显然对您的测试用例有效

但是,如果不能保证
val
处于
状态,则它无效

如果有这种可能性,您应该在检查周围放置一个
try:
/
除外:
(这意味着将其抽象为一个显式循环语句或一个单独的函数),或者使用
条件.get(val,False)
(假设您希望将“不在
条件下
”视为False)

如果不可能的话,最好让代码保持原样;这样,如果你得到“不可能”的数据,你会得到一个异常,而不是一个错误的答案


同时,
==True
比较通常不惯用,也不是一个好主意。正如上面所说:

不要使用
=
将布尔值与
True
False
进行比较

当然,这只是一个指导方针;在某些情况下,您明确希望确保某些内容是
True
,而不仅仅是truthy,在这种情况下,您需要使用
==True
是True
(前者接受其他数值
1
值,后者不接受)。但是如果你没有任何理由这样做,就不要这样做


另外,您会说,“这是一个非常简化的案例,我为一个更大的示例生成了……”我不知道“更大”有多大,但如果
list_2
足够大,您的代码将非常低效

您正在逐个检查列表_1的每个元素与列表_2的每个元素。所以,如果每个列表中有1000个条目,那就是1000000个比较

如果您将
list_2
转换为一个集合,那么您只需对列表1的每个元素执行集合查找,因此它只有1000个哈希和1000个比较,而不是1000000个比较

你可以这样写:

set_2 = set(list_2)
res = [val for val in list_1 if val in set_2 and condition[val]]

你也可以用各种方式简化事情。这些不会影响性能,但可以提高可读性和语义合理性。特别是,正如ojy所说,通过使用集合交集、集合理解或两者,您可以轻松地将这两个条件组合为一个条件。例如:

set_2 = set(list_2) & {k for k, v in condition.items() if v}
res = [val for val in list_1 if val in set_2]
通过使用另一个集合交点,您可以进一步了解这一点:

res = set(list_1) & set(list_2) & {k for k, v in condition.items() if v}
然而,这一个改变了语义:它丢弃了
list_1
中的任何重复值,也丢弃了顺序。如果这些都是可以接受的,那么这样做可能是个好主意,只是为了让人们清楚地看到,复制是不可能的,顺序是不相关的。如果没有,显然不要这样做



最后,值得一提的是,您是否首先使用了错误的数据结构。你能把列表作为一个集合而不是一个列表来构建吗?或
列表\u 1
?您能否将
条件
构建为一组true键,而不是将dict映射为true和False?

您始终可以在解释器中测试一行程序。而且,
==True
是正确的。您应该这样做:
如果列表2中的val和条件[val]
@iCodez-这是一个非常简单的例子,我为一个更大的例子制作了这个例子,我无法直观地检查。我想确保它在一般情况下是有效的,而不仅仅是针对发布的示例。如果val不在字典中,它将中断。我会将条件转换为第三个列表,该列表只包含条件所包含的键,并取三个列表的交集。我不知道您的“较大示例”有多大,但是如果
list_2
足够大,这将是非常低效的,因为您要逐个检查
list_1
的每个元素与
list_2
的每个元素。考虑将<代码> ListS2 2/代码>转换为一个集合。为什么使用<代码>集合?设置< /代码>?它在2.6中被弃用,在3.x中消失。除非您需要与Python的古老版本向后兼容(但不是太古老,因为2.3没有排序的
,2.2没有
集,1.5没有列表理解…),否则这比您将来需要的兼容性更傻。根据您的建议,我已经使它与Python的两个稳定版本兼容:)。然而,很少有人使用老版本的Python。多数票被考虑在内。
res = set(list_1) & set(list_2) & {k for k, v in condition.items() if v}