使用增量对数组数组进行排序

Sorting an array of arrays with the delta

我有一个这样的数组:

[[300, 400], [200, 300], [500, 600], [400, 200]] 

我想要的是制作另一个按其他值排序的数组,第一项应该更接近该值,我尝试按增量排序:

c = [300, 50]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].sort do |a, b|
  a_width_delta = a.first - c.first
  a_height_delta = a.last - c.last
  b_width_delta = b.first - c.first
  b_height_delta = b.last - c.last

  (a_width_delta + a_height_delta) <=> (b_width_delta + b_height_delta)
end
p "Input #{c}"
p f
c = [300, 400]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].sort do |a, b|
  a_width_delta = a.first - c.first
  a_height_delta = a.last - c.last
  b_width_delta = b.first - c.first
  b_height_delta = b.last - c.last

  (a_width_delta + a_height_delta) <=> (b_width_delta + b_height_delta)
end
p "Input #{c}"
p f

这个条件是正确的:

$> ruby fo.rb
"Input [300, 50]"
[[200, 300], # other elements] # correct!

另一个错误:

"Input [300, 400]"
[[200, 300], # other elements] # wrong!

应该是:

"Input [300, 400]"
[[300, 400], # other elements] # correct!

我只需要一个在第一个索引处具有最接近值的数组。

我希望您的 "correct" 输出示例是错误的。否则我不明白这些要求。 :-)

如果我没理解错的话,这个想法是从一个起点开始按每个元素的 "distance" 排序。距离定义为分量值之差的总和。例如。对于 x1, y1x2, y2|x2-x1| + |y2-y1|.

缺少的是绝对值...您当前的代码 "rewards" 负数不当。

这是一个采用每次计算的绝对值的版本。它不会产生您想要的输出。如果您真的想要您指定的输出,请描述您使用什么规则来确定它。

c = [300, 50]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].sort do |a, b|
  a_width_delta = (a.first - c.first).abs
  a_height_delta = (a.last - c.last).abs
  b_width_delta = (b.first - c.first).abs
  b_height_delta = (b.last - c.last).abs

  (a_width_delta + a_height_delta) <=> (b_width_delta + b_height_delta)
end
p "Input #{c}"
p f

# Output:
# "Input [300, 50]"
# [[400, 200], [200, 300], [300, 400], [500, 600]]


c = [300, 400]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].sort do |a, b|
  a_width_delta = (a.first - c.first).abs
  a_height_delta = (a.last - c.last).abs
  b_width_delta = (b.first - c.first).abs
  b_height_delta = (b.last - c.last).abs

  (a_width_delta + a_height_delta) <=> (b_width_delta + b_height_delta)
end
p "Input #{c}"
p f

# Output:
# "Input [300, 400]"
# [[300, 400], [200, 300], [400, 200], [500, 600]]

编辑

根据对您问题的编辑,您似乎只关心输出数组中的第一个元素(最小值)。在那种情况下,为什么不只计算最小值?

c = [300, 50]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].min_by { |x| (x.first - c.first).abs + (x.last - c.last).abs }
p "Input #{c}"
p f

# Output:
# "Input [300, 50]"
# [400, 200]


c = [300, 400]
f = [[200, 300], [300, 400], [400, 200], [500, 600]].min_by { |x| (x.first - c.first).abs + (x.last - c.last).abs }
p "Input #{c}"
p f

# Output:
# "Input [300, 400]"
# [300, 400]
▶ λ = lambda do |input, point|
    [input, point].transpose # to ease the subtraction
                  .map { |e| e.reduce &:- } # distances [x, y]
                  .map(&:abs) # absolute values of distances
                  .reduce(:+) # total distance
  end

▶ [[200, 300], [300, 400], [400, 200], [500, 600]].min_by &λ.curry[[300, 50]]
#⇒ [400, 200]

▶ [[200, 300], [300, 400], [400, 200], [500, 600]].min_by &λ.curry[[300, 400]]
#⇒ [300, 400]