我有array
的{{1}}:
Hash
我必须首先按hash =
[
{
distance: 0.3997651063189804, project_id: 1, project_name: "Project 1", project_dependents_ids: [4]
},
{
distance: 0.414026818885287, project_id: 2, project_name: "Project 2", project_dependents_ids: [1]
},
{
distance: 0.6259577862775509, project_id: 3, project_name: "Project 3", project_dependents_ids: []
},
{
distance: 0.43719371056189227, project_id: 4, project_name: "Project 4", project_dependents_ids: [3]
},
{
distance: 0.4341702282185951, project_id: 5, project_name: "Project 5", project_dependents_ids: []
}
]
对其进行排序,但如果distance
有project
(自我关联),则必须在{{{}之后进行排序1}} 关联。
例如:
按距离进行简单排序,如下所示:
project_dependents
...将导致:
但这个结果不是我想要的100%。我想通过project
对它进行排序。例如:
结果必须是:
这只是一个简单的示例。一个项目可以有很多自我关联ID等等。
所以,我想知道如何实现这种排序。也许一般的想法会有所帮助。我在这里做的所有实现都得到了巨大的代码和不正确的结果。
答案 0 :(得分:3)
如果没有distance
要求,Ruby的TSort
就是这项工作的工具。但是,我无法弄清楚如何在拓扑排序中添加额外的要求,所以......
一个想法是从排序的数组开始,然后通过将每个元素推过其所有依赖项来重新排列它。例如。从排序顺序开始
[3, 4, 5, 2, 1]
我们单独留下3个(没有家属),单独留下4个(其所有家属都留下),单独留下5个(没有家属),1个之后推2(因为1是其依赖性和右侧),然后单独留下1个(其所有家属都留在其中),并且单独留下2个(其所有家属都留在其中)。
如果您有循环依赖关系,这将导致无限循环。它可以防范,但我会把它作为练习留给读者:)(例如,你可以在Set
推送所有节点的curr
,并在{{1}时清除它}递增;如果您尝试重新推送相同的,则引发错误)
curr
编辑:所有array = hash # because your naming makes no sense :)
hash = array.each.with_object({}) { |o, h| h[o[:project_id]] = o }
order = array.map { |o| o[:project_id] }.sort_by { |id| -hash[id][:distance] }
order.each_index do |curr|
dependents = hash[order[curr]][:project_dependents_ids]
max_dep_index = dependents.map { |d| order.index(d) }.max
if max_dep_index&.> curr
order[curr .. max_dep_index - 1], order[max_dep_index] =
order[curr + 1 .. max_dep_index], order[curr]
redo
end
end
result = hash.values_at(*order)
次来电都不是非常有效,我觉得应该可以做得更好......
EDIT2:让循环更加Rubyish。