Python:检查项目是否存在可变数量的列表

Python:检查项目是否存在可变数量的列表

问题描述:

我正在研究一个小型搜索引擎,并且我迷失了某个特定点。我有多个包含项目的列表,我想检查所有列表中存在哪些项目。列出的量可以改变,因为它们是基于搜索查询的单词数创建的,以做到:Python:检查项目是否存在可变数量的列表

index_list = [[] for i in range((len(query)+1))] 

我想我开始找出最短的名单是什么,因为这是最大需要检查的项目数量。因此,例如,用三个词的搜索查询:

index_list[1]=[set(1,2,3,4,5)] 
index_list[2]=[set(3,4,5,6,7)] 
index_list[3]=[set(4,5,6,7)] 

shortest_list = index_list[3] 

(最短的名单是什么,与功能,现在还没有相关想通了)。

现在我想检查最短列表index_list [3]的项目是否也存在于其他列表中。在这种情况下,总共有3个列表,但是当输入较长的搜索查询时,列表数量会增加。我认为做循环的东西,如:

result = [] 
for element in shortest_list: 
    for subelement in element: 
     for element2 in index_list[1]: 
      if subelement in element2: 
       for element3 in index_list[2]: 
        if subelement in element3: 
         result.append(subelement) 

所以,结果应该是:

[4, 5] 

因为所有列表中存在的这些项目。

但是,当有更多的列表时,上面的循环将不起作用。如前所述,我不知道列表的数量,因为它取决于搜索查询中单词的数量。所以基本上我的循环深度取决于我拥有的列表数量。

在做研究时,我发现一些提示递归的帖子可能会完成这项工作。不幸的是,我不擅长Python。

有什么建议吗?

提前致谢!

+0

看看['itertools.product'](https://docs.python.org/2/library/itertools.html#itertools.product),这对于unpicking嵌套循环很有用 – jonrsharpe 2014-11-06 11:26:19

只需使用所有sets和使用set.intersection找到共同的元素,也{1,2,3,4,5}是如何创建一组整数的不set(1,2,3,4,5)

index_list = [set() for i in range(4)] 
index_list[0].update({1,2,3,4,5}) 
index_list[1].update({3,4,5,6,7}) 
index_list[2].update({4,5,6,7}) 

shortest_list = index_list[2] 

print(shortest_list.intersection(*index_list[:2])) 
set([4, 5]) 
+0

谢谢!我没有意识到交集采用了任意数量的参数,这使得我的代码非常冗余。 – 2014-11-06 11:45:53

+0

是的,'* index_list [:2]'获取列表中的每个集合,不包括设置为'shortest_list'的最后一个集合。 – 2014-11-06 11:48:19

+0

这有帮助,谢谢!另一个问题是:* index_list后面的数字(在这种情况下是2)是手动放入的?在你的代码中,即使列表数量增加,它仍然保留:2。因为它需要适应列表的数量,对吗? – Ilse 2014-11-06 13:07:28

尝试去了解它相反的方式:一是通过执行类似

index_list_list = [] 
for ix_list in get_index_lists(): #Or whatever 
    index_list_list.append(ix_list) 

然后你可以通过所有这些循环,消除你的“REMAINING_ITEMS”的元素,让所有索引列表的列表列表中,如果它们不包含在其他:

remaining_items = shortest_list 
for index_list in index_list_list: 
    curr_remaining_items = copy(remaining_items) 
    for element in curr_remaining_items: 
     if element not in index_list: 
      remaining_items.remove(element) 

你最后的“REMAINING_ITEMS”名单,然后将包含通用于所有列表中的元素。

我用你的方法编写代码。你可以试试下面的代码:

index_list=['1','2','3','4','5'] 
index_list1=['3','4','5','6','7'] 
index_list2=['4','5','6','7'] 

result = [] 
for element in index_list: 
    for subelement in element: 
     for element2 in index_list1: 
      if subelement in element2: 
       for element3 in index_list2: 
        if subelement in element3: 
         result.append(subelement) 
print result 

输出:

['4', '5'] 

有点令人困惑,你似乎有一些东西影响内置型,恰好为这种类型的工作而建造。

subset = set(shortest_list) 
# Use map here to only lookup method once. 
# We don't need the result, which will be a list of None. 
map(subset.intersection_update, index_lists) 

# Alternative: describe the reduction more directly 
# Cost: rebuilds a new set for each list 
subset = reduce(set.intersection, index_lists, set(shortest_list)) 

注:由于帕德里克在他的回答,set.intersection指示,set.intersection_update都接受的自变量的任意数量,因此没有必要使用地图或减少这种情况。

由于交集可以优化为较小集合的大小,但是列表交集需要扫描列表,所以所有列表已经是集合,这也是最好的。