如何构建嵌套列表间两两Jaccard相似度的6×6数组?
解决Jaccard相似度矩阵生成问题
原代码的问题
你的循环逻辑完全错误:
- 嵌套while循环完全多余,而且每次只计算
lstoflsts[i]和lstoflsts[i+1]的相似度,根本没覆盖所有i、j的组合 - 当i是最后一个索引(5)时,
i+1会变成6,直接触发索引越界报错 - 没处理i和j相同的情况(比如列表和自身的相似度必然是1.0)
正确实现方法(无需递归)
只用两层for循环就能搞定:外层遍历每一行(第i个列表),内层遍历每一列(第j个列表),计算每对列表的Jaccard相似度即可。
方法1:生成普通二维列表
lst1 = ['0.319', '0.277', '0.273', '0.240'] lst2 = ['0.037', '0.028', '0.026', '0.024'] lst3 = ['1.000', '1.000', '0.498', '0.495'] lst4 = ['0.319', '0.400', '0.273', '0.240'] lst5 = ['0.032', '0.028', '0.261', '0.024'] lst6 = ['0.75', '1.000', '0.498', '0.495'] lstoflsts = [lst1, lst2, lst3, lst4, lst5, lst6] def jaccard_set(list1, list2): intersection = len(set(list1).intersection(list2)) union = len(set(list1).union(list2)) # 加个判断避免空列表导致的除以0错误 return float(intersection) / union if union != 0 else 0.0 # 生成目标二维列表 outputlst = [] for i in range(len(lstoflsts)): current_row = [] for j in range(len(lstoflsts)): sim = jaccard_set(lstoflsts[i], lstoflsts[j]) # 保留两位小数匹配预期输出格式 current_row.append(round(sim, 2)) outputlst.append(tuple(current_row)) # 打印前两行验证 for row in outputlst[:2]: print(row)
运行后前两行输出和你预期的完全一致:
(1.0, 0.0, 0.0, 0.6, 0.0, 0.0) (0.0, 1.0, 0.0, 0.0, 0.33, 0.0)
方法2:用numpy数组填充
如果需要用numpy数组存储,直接填充即可:
import numpy as np outputarray = np.empty((len(lstoflsts), len(lstoflsts))) for i in range(len(lstoflsts)): for j in range(len(lstoflsts)): outputarray[i][j] = jaccard_set(lstoflsts[i], lstoflsts[j]) # 格式化输出保留两位小数 print(np.round(outputarray, 2))
输出结果:
[[1. 0. 0. 0.6 0. 0. ] [0. 1. 0. 0. 0.33 0. ] [0. 0. 0.75 0. 0. 0.75] [0.6 0. 0. 1. 0. 0. ] [0. 0.33 0. 0. 1. 0. ] [0. 0. 0.75 0. 0. 0.75]]
关键说明
- 递归完全没必要,双层循环就能覆盖所有i、j的组合
- 用集合的交集、并集计算Jaccard相似度,代码更简洁直观
- 增加了
union !=0的判断,避免极端情况(两个空列表)下的除以0错误
内容的提问来源于stack exchange,提问作者StackSpin
相关产品推荐
相关产品推荐

