You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中sorted(by:)排序顺序不符合预期问题排查

问题分析与解决方案

问题根源:闭包不满足严格弱序要求

你的排序闭包return parents[rhs]!.contains(lhs)看似合理,但实际上违反了Swiftsorted方法强制要求的严格弱序规则,导致排序算法无法正确生成预期顺序。

严格弱序的核心要求之一是等价关系的传递性:如果a和b等价(既不a应该排在b前,也不b应该排在a前),b和c等价,那么a和c必须也等价。但你的闭包破坏了这一点:

  • 比如21和2:互相不在对方的父列表中,属于等价关系
  • 2和4:同样互相不在对方父列表中,属于等价关系
  • 但21是4的父节点,21和4并不等价(21应该排在4前)

这种等价关系的断裂会让排序算法(如Timsort)失去可靠的排序依据,最终返回未定义的随机结果。

另外,你的闭包只处理了直接父子关系的比较,完全没有考虑间接依赖(比如21是5的父,5是4的父,21也应该排在4前),即使闭包满足严格弱序,也无法保证间接依赖的顺序正确。

正确解决方案:拓扑排序

你的需求本质是对**有向无环图(DAG)**进行拓扑排序——确保所有父节点排在子节点之前。普通的两两比较排序无法处理这类依赖关系,必须用专门的拓扑排序算法实现:

let parents: [Int: [Int]] = [2: [],
                             4: [5, 21],
                             5: [21],
                             6: [],
                             9: [],
                             10: [],
                             21: []]

// 构建父节点到子节点的映射,以及每个节点的入度(未排序的父节点数量)
var childrenMap: [Int: [Int]] = [:]
var inDegree: [Int: Int] = [:]

for (node, parentList) in parents {
    // 初始化当前节点的入度为父节点数量
    inDegree[node] = parentList.count
    // 给每个父节点添加当前节点作为子节点
    for parent in parentList {
        childrenMap[parent, default: []].append(node)
    }
}

// 初始化队列:所有没有父节点(入度为0)的节点
var queue = inDegree.filter { $0.value == 0 }.map { $0.key }
var sortedResult: [Int] = []

while !queue.isEmpty {
    let currentNode = queue.removeFirst()
    sortedResult.append(currentNode)
    
    // 遍历当前节点的所有子节点,将它们的入度减1
    for child in childrenMap[currentNode] ?? [] {
        inDegree[child]! -= 1
        // 当子节点入度为0时,说明所有父节点已排序,加入队列
        if inDegree[child]! == 0 {
            queue.append(child)
        }
    }
}

print(sortedResult)
// 输出示例:[2, 9, 6, 10, 21, 5, 4](无依赖节点顺序可任意,核心依赖顺序21→5→4必满足)

算法逻辑说明:

  1. 构建映射:先把父节点到子节点的关系反向存储,同时记录每个节点需要等待多少个父节点排序完成(入度)。
  2. 初始化队列:先把所有没有父节点的节点加入队列,这些节点可以直接放在结果里。
  3. 迭代排序:每次从队列取出一个节点加入结果,然后把它的子节点的入度减1——当子节点的入度变为0,说明它的所有父节点都已排好序,就可以加入队列等待处理。

这种方法能确保所有直接和间接的父节点都排在子节点之前,完全满足你的需求。

内容的提问来源于stack exchange,提问作者Remco Poelstra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 03:34:54