如何在python中有效地搜索列表

时间:2019-06-17 01:38:43

标签: python list

我有一本只有四个键(mydictionary)和一个列表(mynodes)的字典,如下所示。

    mydictionary = {0: {('B', 'E', 'G'), ('A', 'E', 'G'), ('A', 'E', 'F'), ('A', 'D', 'F'), ('C', 'D', 'F'), ('C', 'E', 'F'), ('A', 'D', 'G'), ('C', 'D', 'G'), ('C', 'E', 'G'), ('B', 'E', 'F')}, 
1: {('A', 'C', 'G'), ('E', 'F', 'G'), ('D', 'E', 'F'), ('A', 'F', 'G'), ('A', 'B', 'G'), ('B', 'D', 'F'), ('C', 'F', 'G'), ('A', 'C', 'E'), ('D', 'E', 'G'), ('B', 'F', 'G'), ('B', 'C', 'G'), ('A', 'C', 'D'), ('A', 'B', 'F'), ('B', 'D', 'G'), ('B', 'C', 'F'), ('A', 'D', 'E'), ('C', 'D', 'E'), ('A', 'C', 'F'), ('A', 'B', 'E'), ('B', 'C', 'E'), ('D', 'F', 'G')}, 
2: {('B', 'D', 'E'), ('A', 'B', 'D'), ('B', 'C', 'D')}, 
3: {('A', 'B', 'C')}}

mynodes = ['E', 'D', 'G', 'F', 'B', 'A', 'C']

我正在检查mynodes列表中的每个节点在mydictionary的每个键中有多少次。例如,考虑上面的字典和列表。

输出应为;

{'E': [(0, 6), (1, 8), (2, 1), (3, 0)], 
'D': [(0, 4), (1, 8), (2, 3), (3, 0)], 
'G': [(0, 5), (1, 10), (2, 0), (3, 0)], 
'F': [(0, 5), (1, 10), (2, 0), (3, 0)], 
'B': [(0, 2), (1, 9), (2, 3), (3, 1)], 
'A': [(0, 4), (1, 9), (2, 1), (3, 1)], 
'C': [(0, 4), (1, 9), (2, 1), (3, 1)]}

例如,考虑E。在0键中显示6次,在1键中显示8次,在2键中显示2次,在3键中显示0次。

我当前的代码如下。

    triad_class_for_nodes = {}


    for node in mynodes:
        temp_list = []

        for key, value in mydictionary.items():                
            temp_counting = 0

            for triad in value:
                #print(triad[0])
                if node in triad:
                    temp_counting = temp_counting + 1
            temp_list.append(tuple((key, temp_counting)))

        triad_class_for_nodes.update({node: temp_list})
    print(triad_class_for_nodes)

这对于较小的字典值可以很好地工作。

但是,在我的真实数据集中,我字典中的4个键中的每个键的值列表中都有成千上万的元组。因此,我现有的代码确实效率很低,并且需要几天的时间才能运行。

当我寻找如何提高效率时,我遇到了这个问题(Fastest way to search a list in python),该问题建议将值列表归为一组。我也尝试过这个。但是,运行还需要几天的时间。

我只是想知道在python中是否有更有效的方法。 我很高兴将现有的数据格式转换为不同的结构(例如pandas dataframe),以提高效率。

下面附有mydictionarymynodes的小样本,以进行测试。 https://drive.google.com/drive/folders/15Faa78xlNAYLPvqS3cKM1v8bV1HQzW2W?usp=sharing

  • mydictionary:请参见triads.txt

    with open("triads.txt", "r") as file: mydictionary = ast.literal_eval(file.read)

mynodes:请参阅nodes.txt

with open("nodes.txt", "r") as file:  
   mynodes = ast.literal_eval(file.read) 

很高兴在需要时提供更多详细信息。

2 个答案:

答案 0 :(得分:1)

自从标记了pandas之后,我们首先需要将您的字典转换为pandas数据帧,然后我们将其stack转换为crosstab

s=pd.DataFrame.from_dict(mydictionary,'index').stack()


s = pd.DataFrame(s.values.tolist(), index=s.index).stack()
pd.crosstab(s.index.get_level_values(0),s)
col_0  A  B  C  D  E   F   G
row_0                       
0      4  2  4  4  6   5   5
1      9  9  9  8  8  10  10
2      1  3  1  3  1   0   0
3      1  1  1  0  0   0   0

更新

s=pd.crosstab(s.index.get_level_values(0), s).stack().reset_index()

s[['row_0',0]].apply(tuple,1).groupby(s['col_0']).agg(list).to_dict()

答案 1 :(得分:1)

如果您不使用熊猫,则可以使用Collection中的Counter来做到这一点:

from collections import Counter,defaultdict
from itertools import product
counts = Counter((c,k) for k,v in mydictionary.items() for t in v for c in t )
result = defaultdict(list)
for c,k in product(mynodes,mydictionary):
    result[c].append((k,counts[(c,k)]))

print(result)
{'E': [(0, 6), (1, 8), (2, 1), (3, 0)],
 'D': [(0, 4), (1, 8), (2, 3), (3, 0)],
 'G': [(0, 5), (1, 10), (2, 0), (3, 0)],
 'F': [(0, 5), (1, 10), (2, 0), (3, 0)],
 'B': [(0, 2), (1, 9), (2, 3), (3, 1)],
 'A': [(0, 4), (1, 9), (2, 1), (3, 1)],
 'C': [(0, 4), (1, 9), (2, 1), (3, 1)]}

Counter将管理mydictionary密钥和节点的每个组合的计数实例。然后,您可以使用这些计数来创建预期的输出。

编辑:扩展计数行:

counts = Counter()                          # initialize Counter() object
for key,tupleSet in mydictionary.items():   # loop through dictionary
    for tupl in tupleSet:                   # loop through tuple set of each key
        for node in tupl:                   # loop through node character in each tuple
            counts[(node,key]] += 1         # count 1 node/key pair