在ruby on rails中合并数组的数组



我有一个像下面这样的数组

[["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"

假设:

  • aArrayHash
  • a的格式在原文章
  • 中提供
  • 对于a中的b元素,b[0]是唯一的

我要做的第一件事是,如果aArray,然后将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

最新更新