I would like to intersect two nested lists:
我想交叉两个嵌套列表:
source = [['one', 'two', 'three'], ['four', 'five', 'six'], ['seven', 'eight', 'nine']]
target = [['three', 'whatever'], ['four', 'whatever'], ['whatever', 'whatever']]
So I can return the lists in source
where intersections were found:
所以我可以在源代码中返回找到交叉点的列表:
result = [['one', 'two', 'three'], ['four', 'five', 'six']]
How can I do this using lambda
?
我怎么能用lambda做到这一点?
2 个解决方案
#1
5
You can use set to check if there is any intersection between elements:
您可以使用set来检查元素之间是否存在任何交集:
[s for s in source if any(set(s) & set(t) for t in target)]
# [['one', 'two', 'three'], ['four', 'five', 'six']]
This could be slightly more efficient if convert the target to a list of sets before hand:
如果先将目标转换为集合列表,这可能会稍微提高效率:
target_set = [set(t) for t in target]
[s for s in source if any(set(s) & t for t in target_set)]
When saying lambda
, maybe you need a filter
function:
说lambda时,也许你需要一个过滤功能:
filter(lambda s: any(set(s) & t for t in target_set), source)
Or in python 3:
或者在python 3中:
list(filter(lambda s: any(set(s) & t for t in target_set), source))
It seems like your logic is equivalent to the following as @JohnColeman commented:
看起来你的逻辑与@JohnColeman评论的相同:
target_set = {j for i in target for j in i}
filter(lambda s: set(s) & target_set, source)
# [['one', 'two', 'three'], ['four', 'five', 'six']]
#2
2
You can simply use set.difference
in the lambda
combined with a filter:
您可以简单地在lambda中使用set.difference并结合过滤器:
list(filter(lambda s: set(s).difference(*target) != set(s),
source))
This will keep any list that contains at least one item that is in any of the target
-lists.
这将保留包含任何目标列表中的至少一个项目的任何列表。
Or if you don't like set
s you can do the checks explicitly:
或者,如果您不喜欢集合,您可以明确地进行检查:
list(filter(lambda s: any(item in sublist for sublist in target for item in s),
source))
#1
5
You can use set to check if there is any intersection between elements:
您可以使用set来检查元素之间是否存在任何交集:
[s for s in source if any(set(s) & set(t) for t in target)]
# [['one', 'two', 'three'], ['four', 'five', 'six']]
This could be slightly more efficient if convert the target to a list of sets before hand:
如果先将目标转换为集合列表,这可能会稍微提高效率:
target_set = [set(t) for t in target]
[s for s in source if any(set(s) & t for t in target_set)]
When saying lambda
, maybe you need a filter
function:
说lambda时,也许你需要一个过滤功能:
filter(lambda s: any(set(s) & t for t in target_set), source)
Or in python 3:
或者在python 3中:
list(filter(lambda s: any(set(s) & t for t in target_set), source))
It seems like your logic is equivalent to the following as @JohnColeman commented:
看起来你的逻辑与@JohnColeman评论的相同:
target_set = {j for i in target for j in i}
filter(lambda s: set(s) & target_set, source)
# [['one', 'two', 'three'], ['four', 'five', 'six']]
#2
2
You can simply use set.difference
in the lambda
combined with a filter:
您可以简单地在lambda中使用set.difference并结合过滤器:
list(filter(lambda s: set(s).difference(*target) != set(s),
source))
This will keep any list that contains at least one item that is in any of the target
-lists.
这将保留包含任何目标列表中的至少一个项目的任何列表。
Or if you don't like set
s you can do the checks explicitly:
或者,如果您不喜欢集合,您可以明确地进行检查:
list(filter(lambda s: any(item in sublist for sublist in target for item in s),
source))