我有一个像下面这样的数组
[["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]]
我想要下面的结果
"GJ, MP, KL, HR, MH"
数组["GJ","MP"]
的第一个元素在answer_string = "GJ, MP"
中添加现在找到MP
,它是这个数组的最后一个元素,在另一个应该是第一个元素的地方,比如["MP","KL"]
之后,我必须将KL
添加到answer_string = "GJ, MP, KL"
这是我想要的输出
给定
ary = [["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]]
(其中每个元素实际上是你需要遍历的简单图中的一条边)你的任务可以用一种非常直接的方式解决:
acc = ary.first.dup
ary.size.times do
# Find an edge whose "from" value is equal to the latest "to" one
next_edge = ary.find { |a, _| a == acc.last }
acc << next_edge.last if next_edge
end
acc
#=> ["GJ", "MP", "KL", "HR", "MH"]
这里的缺点是它的二次时间(每次迭代都要搜索整个数组),如果初始数组足够大,这将严重打击您。如果使用一些辅助数据结构(例如哈希)进行更快的查找,速度会更快。Smth。像
head, *tail = ary
edges = tail.to_h
tail.reduce(head.dup) { |acc, (k, v)| acc << edges[acc.last] }
#=> ["GJ", "MP", "KL", "HR", "MH"]
(我没有将结果数组连接到字符串中,但这有点直接)
d = [["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]]
o = [] # List for output
c = d[0][0] # Save the current first object
loop do # Keep looping through until there are no matching pairs
o.push(c) # Push the current first object to the output
n = d.index { |a| a[0] == c } # Get the index of the first matched pair of the current `c`
break if n == nil # If there are no found index, we've essentially gotten to the end of the graph
c = d[n][1] # Update the current first object
end
puts o.join(',') # Join the results
随着问题的急剧变化而更新。从本质上讲,你在一个图中导航。
我使用arr.size.times
来循环
def check arr
new_arr = arr.first #new_arr = ["GJ","MP"]
arr.delete_at(0) # remove the first of arr. arr = [["HR","MH"],["MP","KL"],["KL","HR"]]
arr.size.times do
find = arr.find {|e| e.first == new_arr.last}
new_arr << find.last if find
end
new_arr.join(',')
end
array = [["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]]
p check(array)
#=> "GJ,MP,KL,HR,MH"
假设:
a
是Array
或Hash
a
的格式在原文章 中提供- 对于
a
中的b
元素,b[0]
是唯一的
我要做的第一件事是,如果a
是Array
,然后将a
转换为Hash
,以便更快更容易地查找(这在技术上不是必要的,但它简化了实现,应该提高性能)
a = [["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]]
a.to_h
#=> {"GJ"=>"MP", "HR"=>"MH", "MP"=>"KL", "KL"=>"HR"}
如果路径总是从第一个到链的末端,元素总是一个完整的链,那么借用@KonstantinStrukov的灵感:(如果你喜欢这个选项,那么请给他信用✔️)
a.to_h.then {|edges| edges.reduce { |acc,_| acc << edges[acc.last] }}.join(",")
#=> "GJ,MP,KL,HR,MH"
<子>警告:如果原始元素中有未连接的元素,则结果将包含nil
(以末尾逗号表示)。这可以通过添加Array#compact
来解决,但它也会导致对每个断开的元素进行不必要的遍历。子>
原来我们可以使用递归方法查找从给定键到路径末端的路径。默认键为a[0][0]
def navigate(h,from:h.keys.first)
return unless h.key?(from)
[from, *navigate(h,from:h[from]) || h[from]].join(",")
end
解释:
navigation(h,from:h.keys.first)
-要遍历的哈希值和遍历的起点return unless h.key?(key)
如果Hash
不包含from
键返回nil
(链的末端)[from, *navigate(h,from:h[from]) || h[from]].join(",")
-构建from
键的Array
和查找from
键的递归结果,如果递归返回nil
,则附加最后一个值。然后简单地将Array
转换为String
,并用逗号连接元素。
用法:
a = [["GJ","MP"],["HR","MH"],["MP","KL"],["KL","HR"]].to_h
navigate(a)
#=> "GJ,MP,KL,HR,MH"
navigate(a,from: "KL")
#=> "KL,HR,MH"
navigate(a,from: "X")
#=> nil