按周期排序项目

时间:2016-01-08 00:39:57

标签: ruby-on-rails arrays ruby sorting multidimensional-array

我无法解释我在寻找什么,所以我将提供一个例子,让我们说我有这个数组:

[
  [1, 2],
  [1, 3],
  [1, 4],
  [2, 3],
  [2, 4],
  [3, 4]
]

而不是按第一列对其进行排序,我希望它在第一列中循环,因此它将代替1, 1, 1, 2, 2, 31, 2, 3, 1, 2, 1

导致:

[
  [1, 2],
  [2, 3],
  [3, 4],
  [1, 3],
  [2, 4],
  [1, 4]
]

更好的是,如果它可以循环通过两列以尽可能地防止连续两个数字,理想的解决方案是将原始数组排序为:

[
  [1, 2],
  [3, 4],
  [1, 3],
  [2, 4],
  [1, 4],
  [2, 3]
]

导致每个内部数组的重复数之间的最大间距(两个列都被考虑在内)。

我希望我已经提供了足够的信息,我将非常感谢任何建议,到目前为止,我相当无能为力,搜索没有给我任何东西。

3 个答案:

答案 0 :(得分:2)

我只会解决你问题的第一部分,因为我不明白你的意思。“如果它可以循环通过两列以防止连续两个数字,那就更好了......” 。 “尽可能”这一条款特别麻烦,因为它指的是一个未指明的标准。

git push - error. 成为您的数组。元素在您的示例中排序,但如果不是,则第一步是:

arr

请参阅Array#sort!Array#<=>,了解Ruby如何排序其元素为数组的数组。

有许多方法可以获得所需的排序。这是一个使用Enumerable#chunk

的人
arr.sort!

步骤如下:

arr.chunk(&:first).flat_map {|_,a| a.map.with_index {|i,b| [b,i]}}.sort.map(&:last)
  #=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]

我们可以看到这个枚举器的元素,它们被Enumerator#each(调用Array#each)传递给块,通过将它转换为数组:

e = arr.chunk(&:first)
  #=> #<Enumerator: #<Enumerator::Generator:0x007fa01a8141d0>:each> 

继续:

e.to_a
  #=> [[1, [[1, 2], [1, 3], [1, 4]]], [2, [[2, 3], [2, 4]]], [3, [[3, 4]]]] 

让我们更仔细地看一下f = e.flat_map { |_,a| a.map.with_index { |i,b| [b,i] } } #=> [[0, [1, 2]], [1, [1, 3]], [2, [1, 4]], [0, [2, 3]], [1, [2, 4]], [0, [3, 4]]] g = f.sort #=> [[0, 1, 2], [0, 2, 3], [0, 3, 4], [1, 1, 3], [1, 2, 4], [2, 1, 4]] g.map(&:last) #=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]] 的计算:

f

您可以将h = e.flat_map #=> #<Enumerator: #<Enumerator: #<Enumerator::Generator:0x007fa01a8141d0>:each>:flat_map> h.to_a #=> [[1, [[1, 2], [1, 3], [1, 4]]], [2, [[2, 3], [2, 4]]], [3, [[3, 4]]]] 视为“复合”枚举器。

hh的第一个值传递给块,并使用 parallel (或 multiple )由块变量捕获分配

[1, [[1, 2], [1, 3], [1, 4]]]

由于i, a = h.next #=> [1, [[1, 2], [1, 3], [1, 4]]] i #=> 1 a #=> [[1, 2], [1, 3], [1, 4]] 未在块计算中使用,因此习惯上将该块变量替换为局部变量i

我们现在可以执行块计算:

_

其余的计算也是类似的。

答案 1 :(得分:1)

你可以试试这个

def func ary
  ret = []
  # group by first ones, and each sort by second ones
  a = ary.group_by{|i| i[0]}.map{|_,i| i.sort_by{|j| j[1]}}
  # add to ret
  (0...a.map{|i| i.size}.max).map{
    a.map{|i| ret << i.shift}
  }
  ret.compact
end
a = [[1, 2],[1, 3],[1, 4],[2, 3],[2, 4],[3, 4]]
p func(a)
#=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]

答案 2 :(得分:0)

假设初始数组按第一个元素排序:

arr =
  [
    [1, 2],
    [1, 3],
    [1, 4],
    [2, 3],
    [2, 4],
    [3, 4],
  ]

res = []
arr_dup = arr.dup
remaining_values = arr_dup.map { |el| el[0] }
current_value = remaining_values.first
loop do
  arr_dup.each_with_index do |el, index|
    if el[0] >= current_value
      res << el
      current_value = remaining_values.select { |v| v > el[0] }.first || remaining_values.first
      remaining_values.delete_at(remaining_values.index(current_value))
      arr_dup.delete_at(index)
      break
    end
  end
  break if remaining_values.empty?
end

p arr #=> [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
p res #=> [[1, 2], [2, 3], [3, 4], [1, 3], [2, 4], [1, 4]]

几乎没有测试:

[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [5, 1], [20, 2]] =>
[[1, 2], [2, 3], [3, 4], [5, 1], [20, 2], [1, 3], [2, 4], [1, 4]]

[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [5, 1], [5, 2], [20, 2]] =>
[[1, 2], [2, 3], [3, 4], [5, 1], [20, 2], [1, 3], [2, 4], [5, 2], [1, 4]]