代码之家  ›  专栏  ›  技术社区  ›  david 11

检查集合/列表中的每个元素中是否至少有一个元素的最快方法

  •  0
  • david 11  · 技术社区  · 3 年前

    我有以下几点:

    list1 = {"a", "b", "c"}
    
    list2 = [
        {"a", "s", "d", "f"},
        {"q", "w", "e", "c"},
        {"v", "b", "n", "m"},
    ]
    

    现在我想检查列表1中的元素是否在列表2中。list2中的每个元素必须包含list1中的一个元素。

    我目前所做的是(不久前还在stackoverflow上找到它):

    all(list1 & l for l in list2)
    

    这实际上相当快。然而,我现在遇到的问题是,我有数以十亿计的不同列表1,所以我必须想出一个更快的解决方案。我也试过numba,但我很难处理嵌套列表,而且不支持集合。

    我有一堆可以表示这些集合的项目(比如清单2中的集合)。例如,列表2中的第一组由“a”、“s”、“d”和“f”组成。所有这些字符都“删除”了列表2中的第一组字符。

    我现在想做的是找到描述列表2的最短组合。例如:

    list2 = [
        {"a", "s", "d", "f"},
        {"q", "w", "e", "c"},
        {"v", "b", "n", "m"},
        {"v", "l", "p", "o"},
    ]
    

    这里描述列表2的最短组合是a,q,v(a描述第一个元素,q描述第二个元素,v描述第3和4个元素)

    我构建列表1的方式是

    U = set.union(*list2)
    
    for list1 in itertools.combinations(U,3): #i loop over the combinations to find the minimum one, so combinations(U,2), combinations(U,3) ....
         ...
    

    即使对于非常大的数量(100个或数百万个组合),这种方法也非常有效,但仍然有一定的局限性。我想尽量减少。 编辑:list2的数据结构如上所述,是一组包含字符串的集合(在我的例子中是3个字符的组合),因此list1也是一组字符串。

    谢谢

    0 回复  |  直到 3 年前
        1
  •  1
  •   Veedrac    3 年前

    你可以做一个简单的优化,

    not any(map(list1.isdisjoint, list2))
    

    isdisjoint 避免计算完整结果,以及 map 当你只调用一个方法时,它比理解更快。

    然而,如果你想要一个更理想的结果,你必须给出更多关于你试图做什么的细节。特别是,所有数据结构的大小,以及它们包含的元素是什么?

        2
  •  1
  •   Veedrac    3 年前

    我现在想做的是找到描述列表2的最短组合

    这是 Hitting Set Problem ,这是经过充分研究的,并且存在多个解算器, like this one .