希望我能在Ruby中对这个特定的重新排序/排序问题获得一些帮助。
我有一个数组数组,如下:
[['b', 'f'],
['f', 'h'],
['a', 'e'],
['b', 'c'],
['b', 'd'],
['e', 'g'],
['c', 'f'],
['d', 'f'],
['f', 'g'],
['g', 'h']]
每个数组中的第二个元素必须出现在第一个元素之后,所以我想编写一个程序,将它们排序为一个如下所示的数组:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
我正在尝试使用Ruby内置的TSort
库,我也在使用this stack overflow post。
所以我这样做:
class Hash
include TSort
alias tsort_each_node each_key
def tsort_each_child(node, &block)
fetch(node).each(&block)
end
end
def flex_sort(arr)
stuff = arr.map do |head, *tail|
{head => tail}
end
stuff.reduce(&:merge).tsort.reverse
end
sorted = flex_sort(flex)
我有几个问题。首先,我是否走在正确的轨道上?其次,当我运行此代码时,您会注意到初始数组数组不包含带有第一个元素'h'
的数组,因此当我将它们转换为哈希值并尝试运行{{1}时},我得到像.tsort
这样的东西,它迫使我将key 'h' does not exist
放入数组数组中,以便它不会破坏。有办法解决这个问题吗?
答案 0 :(得分:1)
fetch
采用第二个参数,如果它不存在,则为默认值。
fetch(node, []).each(&block)
第二个问题是,当您将阵列&:merge
放入彼此时,您将覆盖以前的值。合并的当前结果是
{"b"=>["d"], "f"=>["g"], "a"=>["e"], "e"=>["g"], "c"=>["f"], "d"=>["f"], "g"=>["h"]}
每个键只有一个值。如果您将其更改为
def flex_sort(arr)
stuff = Hash.new { |hash, key| hash[key] = [] }
arr.each do |head, tail|
stuff[head] << tail
end
stuff.tsort.reverse
end
你的哈希看起来像
{"b"=>["f", "c", "d"], "f"=>["h", "g"], "a"=>["e"], "e"=>["g"], "c"=>["f"], "d"=>["f"], "g" =>["h"]}
现在正在运行您的tsort
["a", "e", "b", "d", "c", "f", "g", "h"]
这非常接近你想要的。不熟悉这种类型,以便知道是否有一种方法可以强迫它在别人之前选择某些键,而这种方法有多种可能性。但这至少可以让你更接近。