如何通过自定义比较功能查找集合相交?

时间:2018-07-11 00:05:06

标签: python set diff intersect

假设我有以下内容:

src = itertools.chain(*map(lambda t: map(lambda u: ((t[0], ) + os.path.splitext(u)), t[2]), os.walk(src_folder)))
dst = itertools.chain(*map(lambda t: map(lambda u: ((t[0], ) + os.path.splitext(u)), t[2]), os.walk(dst_folder)))

这将为两个目录创建格式为[(folder, base name, ext)]的两个列表。

我希望能够找到srcdst中常见的文件。我可以将set(src) & set(dst)设置为documented来完成此操作。但是,如果我只想通过文件夹和基本名称而不是扩展名怎么办?换句话说,如果我想通过自定义规则/函数设置交集怎么办?我该怎么做?

1 个答案:

答案 0 :(得分:0)

  

换句话说,如果我想通过自定义规则/函数设置交集怎么办?我该怎么做?

不能。整个原因集交集如此之快和简单,是因为Python可以立即检查值是否是集合的元素,而不必将其与集合的所有元素进行比较。

但是您可以要做的是在构建集时对其进行变换,然后将它们相交:

{os.path.basename(path) for path in src} & {os.path.basename(path) for path in dst}

问题是,这不会给您全名,这些全名的基本名在交点中,而只是给您一个在交点的基本名。您该如何解决?

最简单的解决方案是使用字典而不是集合。然后,您可以将其键视图用作一组,然后返回并获取相应的值:

srcmap = {os.path.basename(path): path for path in src}
srcisect = srcmap.keys() & {os.path.basename(path) for path in dst}
result = {srcmap[key] for key in srcisect}

这看起来可能需要做很多工作,但是实际上只有4个线性通道而不是3个(并且额外的一个正好位于交叉点而不是原始列表之一),所以在最坏的情况下性能只会更糟一个小的常数因子。