Python中在四层嵌套列表中查找各位置最小非零值的方法
获取嵌套列表中每个位置的最小非零值对应行
问题背景
有一个多层嵌套列表(实际规模远大于示例),需要为每个嵌套位置找到最小非零值对应的完整行,但直接使用min(score, key=lambda row: row[-1])得到的结果不符合预期。
原代码示例
score= [ [[0, 0, 0, 0], [0, 0], [0.14139999999999997]], [[0, 0, 0, 0], [0, 0], [0.19199999999999973]], [[0, 0, 0, 0], [0, 0], [0.1520999999999999]], [[0, 0, 0, 0], [0, 0.13030000000000008], [0]], [[0, 0, 0, 0], [0, 0.06330000000000036], [0]], [[0, 0, 0, 0], [0, 0.0021999999999997577], [0]], [[0, 0, 0, 0], [0.11419999999999986, 0], [0]], [[0, 0, 0, 0], [0.1459999999999999, 0], [0]], [[0, 0, 0, 0], [0.1772999999999998, 0], [0]], [[0, 0, 0, 0.16239999999999988], [0, 0], [0]], [[0, 0, 0, 0.1676000000000002], [0, 0], [0]], [[0, 0, 0.15149999999999997, 0], [0, 0], [0]], [[0, 0, 0.11219999999999963, 0], [0, 0], [0]], [[0, 0.023299999999999876, 0, 0], [0, 0], [0]], [[0, 0.06959999999999988, 0, 0], [0, 0], [0]], [[0.010500000000000398, 0, 0, 0], [0, 0], [0]], [[0.008799999999999919, 0, 0, 0], [0, 0], [0]] ] best_score = min(score, key=lambda row: row[-1]) print(best_score)
问题分析
原代码的key只提取了每行的最后一个子列表进行比较,因此会优先返回最后一个子列表为[0]的行,但这完全忽略了其他位置的非零值。我们需要的是每个嵌套位置各自的最小非零值对应行,而非全局比较某一个子列表。
解决方案
通过遍历所有行,收集每个非零值的位置和对应行,再针对每个位置筛选出最小非零值的行:
score = [ [[0, 0, 0, 0], [0, 0], [0.14139999999999997]], [[0, 0, 0, 0], [0, 0], [0.19199999999999973]], [[0, 0, 0, 0], [0, 0], [0.1520999999999999]], [[0, 0, 0, 0], [0, 0.13030000000000008], [0]], [[0, 0, 0, 0], [0, 0.06330000000000036], [0]], [[0, 0, 0, 0], [0, 0.0021999999999997577], [0]], [[0, 0, 0, 0], [0.11419999999999986, 0], [0]], [[0, 0, 0, 0], [0.1459999999999999, 0], [0]], [[0, 0, 0, 0], [0.1772999999999998, 0], [0]], [[0, 0, 0, 0.16239999999999988], [0, 0], [0]], [[0, 0, 0, 0.1676000000000002], [0, 0], [0]], [[0, 0, 0.15149999999999997, 0], [0, 0], [0]], [[0, 0, 0.11219999999999963, 0], [0, 0], [0]], [[0, 0.023299999999999876, 0, 0], [0, 0], [0]], [[0, 0.06959999999999988, 0, 0], [0, 0], [0]], [[0.010500000000000398, 0, 0, 0], [0, 0], [0]], [[0.008799999999999919, 0, 0, 0], [0, 0], [0]] ] # 用字典存储每个位置的(值, 行)对,位置用元组标识 position_data = {} for row in score: # 遍历第一层子列表(如[0,0,0,0]、[0,0]等) for sub_idx, sub_list in enumerate(row): # 遍历子列表中的每个元素 for elem_idx, value in enumerate(sub_list): if value != 0: pos = (sub_idx, elem_idx) if pos not in position_data: position_data[pos] = [] position_data[pos].append((value, row)) # 为每个位置找到最小非零值对应的行 best_rows = {} for pos, entries in position_data.items(): # 按值排序,取最小的那个条目对应的行 entries.sort(key=lambda x: x[0]) best_rows[pos] = entries[0][1] # 输出结果 for pos, row in best_rows.items(): print(f"位置{pos}的最小非零值对应行: {row}")
代码说明
- 位置标识:用元组
(sub_idx, elem_idx)标记每个嵌套元素的位置,比如(2,0)对应每行的第三个子列表的第一个元素(即原代码中的row[-1][0])。 - 数据收集:遍历所有行,将非零值及其所在行按位置存入字典。
- 筛选最小行:对每个位置的条目按值排序,取第一个(最小)条目对应的行。
输出示例
运行后会输出每个位置的最小非零值对应行,比如:
位置(2, 0)的最小非零值对应行: [[0, 0, 0, 0], [0, 0], [0.14139999999999997]] 位置(1, 1)的最小非零值对应行: [[0, 0, 0, 0], [0, 0.0021999999999997577], [0]] 位置(1, 0)的最小非零值对应行: [[0, 0, 0, 0], [0.11419999999999986, 0], [0]] 位置(0, 3)的最小非零值对应行: [[0, 0, 0, 0.16239999999999988], [0, 0], [0]] 位置(0, 2)的最小非零值对应行: [[0, 0, 0.11219999999999963, 0], [0, 0], [0]] 位置(0, 1)的最小非零值对应行: [[0, 0.023299999999999876, 0, 0], [0, 0], [0]] 位置(0, 0)的最小非零值对应行: [[0.008799999999999919, 0, 0, 0], [0, 0], [0]]
内容的提问来源于stack exchange,提问作者Ondřej Chumchal
相关产品推荐
相关产品推荐

