我有一对矢量数组,它们是围绕多边形的顺时针路径的所有边。问题是,它们的顺序不正确。我想对它们进行排序,以便Array的开始和结束是相同的Vector,并且每个单独的点重叠(端点到起点):
require 'matrix'
unsorted_points = [[Vector[-5, 0], Vector[-3, 2]],
[Vector[-3, 2], Vector[3, 2]],
[Vector[-3, -2], Vector[-5, 0]],
[Vector[3, 2], Vector[5, 0]],
[Vector[3, -2], Vector[-3, -2]],
[Vector[5, 0], Vector[3, -2]]]
sorted_points = [[Vector[-5, 0], Vector[-3, 2]],
[Vector[-3, 2], Vector[3, 2]],
[Vector[3, 2], Vector[5, 0]],
[Vector[5, 0], Vector[3, -2]],
[Vector[3, -2], Vector[-3, -2]],
[Vector[-3, -2], Vector[-5, 0]]]
最常用的Ruby方法是什么?
编辑:向量是来自“矩阵”库的对象,但它们可以像数组一样被索引,例如unsorted_points[0][0][0]
为-5
。
答案 0 :(得分:1)
首先将原始点对数组转换为第一个点为键的映射,第二个值为:
ptsMap = Hash[ * unsorted_points.flatten(1) ]
=> {Vector[-5, 0] => Vector[-3, 2],
Vector[-3, 2] => Vector[3, 2],
Vector[-3, -2] => Vector[-5, 0],
Vector[3, 2] => Vector[5, 0],
Vector[3, -2] => Vector[-3, -2],
Vector[5, 0] => Vector[3, -2] }
然后从第一个点开始,从第二个点到第一个点通过地图链(我注意你的数组不包含“点”,它包含两点之间的边):
ordered_edges = (1...unsorted_points.size).inject ( [unsorted_points.first] ) do |acc,_|
nextPt = acc.last[1]
acc << [ nextPt, ptsMap[nextPt] ]
end
=> [[Vector[-5, 0], Vector[-3, 2]],
[Vector[-3, 2], Vector[3, 2]],
[Vector[3, 2], Vector[5, 0]],
[Vector[5, 0], Vector[3, -2]],
[Vector[3, -2], Vector[-3, -2]],
[Vector[-3, -2], Vector[-5, 0]] ]
请注意,在此上下文中点不具有严格的可比性,因此没有总排序(根据简单sort
的要求。每个点对都描述了一个提供部分排序的边。上面找到了候选总排序假设第一个边的头是你想要的第一个点。
如果原始列表实际上没有描述一组离散连接点,则此技术将失败。使用topological sorting可能会获得更强大的结果。 Ruby有一个库:TSort。通过这种方式,您可以检测到原始边缘集合何时不是单个强连接组件。
答案 1 :(得分:0)
[编辑:我最初提出了两种方法,一种是使用排序,另一种是递归。 @dbenhur表明没有sort
可以工作,因为没有完整的数组元素排序。因此我删除了这种方法。为了记录,我误入歧途的核心是:
unsorted.sort {|v1,v2| (v1 == first || v1[1]==v2[0]) ? -1 : 1}
第二种方法是使用递归。经过反思,很明显我可以在一个简单的循环中做同样的事情,接下来。]
sorted = [unsorted_points.shift]
until unsorted_points.empty?
node = sorted[-1][1]
target = unsorted_points.find {|e| e[0] == node}
sorted << unsorted_points.delete(target)
end
sorted
# => [[Vector[-5, 0], Vector[-3, 2]],
[Vector[-3, 2], Vector[ 3, 2]],
[Vector[ 3, 2], Vector[ 5, 0]],
[Vector[ 5, 0], Vector[ 3, -2]],
[Vector[ 3, -2], Vector[-3, -2]],
[Vector[-3, -2], Vector[-5, 0]]]