Python与条件相交两个列表

时间:2014-11-12 01:42:32

标签: python list-comprehension

只有满足某个条件时,这个单行是最好的方法(没有错误和最有效)才能合并(做交集)两个列表吗?

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

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}

应该返回res = [2 8]。字典condition始终与list_1中的元素具有相同的键。

如果不是我设置的两个列表,我应该如何更改代码?

最后,请注意,这是一个非常简化的案例,我为一个更大的例子制作,我无法用肉眼检查。我想确保我的解决方案一般有效,而不仅仅是发布的示例。

2 个答案:

答案 0 :(得分:3)

这显然适用于您的测试用例。

但是,如果val不能保证在condition,则 无效。

如果有可能,你应该在检查周围放置try: / except:(这意味着将其抽象为显式循环语句或单独的函数),或者使用condition.get(val, False)(假设你想要处理"而不是condition"为假)。

如果这不是一种可能性,那么将代码保留原样可能会更好;那样的话,如果你得到了“不可能”的话。数据,您将获得异常而不是错误的答案。


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

  

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

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


另外,你说,"这是一个非常简化的案例,我为更大的例子制作了......"我不知道有多大"更大"是的,但是如果1足够大,那么你的代码效率会非常低。

您将逐一检查list_1的每个元素与list_2的每个元素。因此,如果每个列表中有1000个条目,那就是1000000个比较。

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

您可以将其写为:

list_2

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

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

您可以通过使用另一个集合交叉点来进一步实现这一点:

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构建为集合而不是列表吗?还是list_2?你可以将list_1构建为一组真正的键,而不是将dict映射到True和False吗?

答案 1 :(得分:2)

您可以使用内置方法设置来执行此操作。 这兼容当前稳定版本的Python - Python 2.7和Python 3.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.

如果您希望您的设置按升序排列,则可以使用" sorted"函数将最后一行替换为

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