简单的设置:我有一个列表(大约40,000个条目)包含字符串列表(每个字符串包含2-15个元素)。我想比较所有子列表,以检查它们是否具有相同的元素(它们最多共享一个)。最后,我想创建一个字典(如果需要,可以用图形表示),其中每个子列表的索引都用作键,其值是与之共享公共元素的其他子列表的索引。
例如
lst = [['dam', 'aam','adm', 'ada', 'adam'], ['va','ea','ev','eva'], ['va','aa','av','ava']]
应提供以下信息:
dic = {0: [], 1: [2], 2: [1]}
我的问题是我找到了一个解决方案,但这在计算上非常昂贵。首先,我编写了一个函数来计算两个列表的交集:
def intersection(lst1, lst2):
temp = set(lst2)
lst3 = [value for value in lst1 if value in temp]
return lst3
然后我将遍历所有列表以检查交叉点:
dic = {}
iter_range = range(len(lst))
#loop over all lists where k != i
for i in iter_range:
#create range that doesn't contain i
new_range = list(iter_range)
new_range.remove(i)
lst = []
for k in new_range:
#check if the lists at position i and k intersect
if len(intersection(mod_names[i], mod_names[k])) > 0:
lst.append(k)
# fill dictionary
dic[i] = lst
我知道for循环很慢,并且我不必要地遍历列表(在上面的示例中,我将1与2进行比较,然后将2与1进行比较),但是我不知道如何更改它使程序运行更快。
答案 0 :(得分:0)
您可以创建一个字典word_occurs_in
来存储数据,该数据将在列表中出现哪个单词,对于您的示例将是:
{'dam':[0],'aam':[0],'adm':[0],'ada':[0],'adam':[0],'va': [1,2],'ea':[1],'ev':[1],'eva':[1],'aa':[2],'av':[2],'ava': [2]}
然后您可以创建一个新的字典,将其命名为result
,在其中应存储最终结果,例如{0: [], 1: [2], 2: [1]}
。
现在,要从result
获取word_occurs_in
,您应该遍历word_occurs_in
的值,并查看列表中是否包含一个以上的元素。如果是这样,则只需要添加result
中除当前观察到的键的值以外的所有其他值。例如,当检查值[1, 2]
(对于键'va'
)时,您将在1
字典中将2
添加到与result
相对应的值,然后将2
添加到与键1
相对应的值。我希望这会有所帮助。
据我所知,代码的最大复杂性来自对40K条目列表进行两次迭代,因此这种方法仅对列表进行一次迭代,但使用了更多的空间。
也许我对自己的解释不够充分,所以代码如下:
from collections import defaultdict
lst = [['dam', 'aam', 'adm', 'ada', 'adam'], ['va', 'ea', 'ev', 'eva'], ['va', 'aa', 'av', 'ava']]
word_occurs_in = defaultdict(list)
for idx, l in enumerate(lst):
for i in l:
word_occurs_in[i].append(idx)
print(word_occurs_in)
result = defaultdict(list)
for v in word_occurs_in.values():
if len(v) > 1:
for j in v:
result[j].extend([k for k in v if k != j])
print(result)