Flutter Dart列表排序异常:长度34且compare返回0时元素位置错乱
为什么Dart中用返回0的compare函数排序列表会出现元素位置错乱?
当对长度为34的int列表使用始终返回0的compare函数排序时,出现了元素位置错乱的情况,代码及结果如下:
问题代码
final nums = List.generate(34, (i) => i); final sortedNums = nums.sorted((a, b) => 0); print('nums: $nums'); print('sortedNums: $sortedNums');
执行结果
nums: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33] sortedNums: [11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 33, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 21]
原因分析
Dart中List.sorted(通常来自package:collection)使用的是不稳定排序算法。不稳定排序的核心特点是:当两个元素被compare函数判定为相等(返回0)时,不会保证它们在排序后的列表中保持原始的相对顺序。
不同长度的列表会触发排序算法的不同分支逻辑,34这个长度刚好触发了算法中的交换操作,导致部分原本有序的元素位置被打乱。
解决方案
如果需要在元素相等时保留原始顺序(即实现稳定排序),可以绑定元素的原始索引,在compare函数中显式比较索引来维持顺序:
final nums = List.generate(34, (i) => i); // 绑定原始索引,相等时通过比较索引确保顺序不变 final sortedNums = nums.asMap().entries .sorted((entryA, entryB) { if (entryA.value == entryB.value) { return entryA.key.compareTo(entryB.key); } return 0; }) .map((entry) => entry.value) .toList(); print('nums: $nums'); print('sortedNums: $sortedNums'); // 输出与原列表完全一致
总结
当compare函数返回0时,不要默认认为元素会保持原始位置——不稳定排序算法会根据自身逻辑调整相等元素的位置。如果需要稳定排序,必须显式处理索引比较,或使用稳定排序的实现。
内容的提问来源于stack exchange,提问作者sm-sayedi
相关产品推荐
相关产品推荐

