只有满足某个条件时,这个单行是最好的方法(没有错误和最有效)才能合并(做交集)两个列表吗?
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
中的元素具有相同的键。
如果不是我设置的两个列表,我应该如何更改代码?
最后,请注意,这是一个非常简化的案例,我为一个更大的例子制作,我无法用肉眼检查。我想确保我的解决方案一般有效,而不仅仅是发布的示例。
答案 0 :(得分:3)
这显然适用于您的测试用例。
但是,如果val
不能保证在condition
,则
如果有可能,你应该在检查周围放置try:
/ except:
(这意味着将其抽象为显式循环语句或单独的函数),或者使用condition.get(val, False)
(假设你想要处理"而不是condition
"为假)。
如果这不是一种可能性,那么将代码保留原样可能会更好;那样的话,如果你得到了“不可能”的话。数据,您将获得异常而不是错误的答案。
同时,== True
比较通常不是惯用的,也不是一个好主意。正如PEP 8所说:
不要使用
True
将布尔值与False
或==
进行比较。
当然这只是一个指导方针;在某些情况下,您明确要确保某些内容为True
,而不仅仅是真实,在这种情况下您需要使用== True
或is 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]