数组数组上的复杂子排序

时间:2013-08-01 15:14:33

标签: ruby sorting

我写了一个快速方法,确认来自网页的数据是否正确排序:

def subsort_columns(*columns)
  columns.transpose.sort
end

适用于基本测试。现在,已经引入了复杂的子类,我很确定我还需要使用数组,因为不能保证哈希以特定的顺序返回。在这种情况下,输入的顺序代表子顺序优先级。

# `columns_sort_preferences` is an Array in the form of:
# [[sort_ascending_bool, column_data]]
# i.e.
# subsort_columns([true, column_name], [false, column_urgency], [true, column_date])
# Will sort on name ascending, then urgency descending, and finally date ascending.
def subsort_columns(*columns_sort_preferences)

end

这就是我被困住的地方。我想干净利落地做到这一点,但除了为任何父类排序中出现的每个子排序推出一个循环之外,我不能想出任何东西......但这听起来不对。

随意提供更好的建议,因为我不依赖于此实现。

以下是一些测试数据:

a =   [1,1,1,2,2,3,3,3,3]
b = %w(a b c c b b a b c)
c = %w(x z z y x z z y z)
subsort_columns([true, a], [false, b], [false, c])
=> [[1, 'c', 'z'], 
    [1, 'b', 'z'], 
    [1, 'a', 'x'], 
    [2, 'c', 'y'], 
    [2, 'b', 'x'], 
    [3, 'c', 'z'],
    [3, 'b', 'z'],
    [3, 'b', 'y'],
    [3, 'a', 'z']]

更新

标记为重新打开,因为我已在我们的代码库中我提供as my own answer 的函数上方的注释中链接到此问题。更不用说我从an answer here那里得到的帮助,清楚地显示了我的问题的解决方案,我想给予我一个正确方向的小费。请不要删除这个问题,这对我很有帮助。如果你不同意,至少留下一条评论,说明你不清楚的事情。

3 个答案:

答案 0 :(得分:1)

a =   [1,1,1,2,2,3,3,3,3]
b = %w(a b c c b b a b c)
c = %w(x z z y x z z y z)
sorted = [a, b, c].transpose.sort do |el1, el2|
  [el1[0], el2[1], el2[2]] <=> [el2[0], el1[1], el1[2]] 
end

对于下行列,反转太空船操作员的左右元素。结果:

[[1, "c", "z"],
 [1, "b", "z"],
 [1, "a", "x"]
 [2, "c", "y"],
 [2, "b", "x"],
 [3, "c", "z"],
 [3, "b", "z"],
 [3, "b", "y"],
 [3, "a", "z"]]

答案 1 :(得分:0)

执行此操作的一种方法是以相反的顺序执行一系列“stable sorts”。从内部排序开始,然后向外部排序。稳定属性意味着内部排序顺序保持不变。

不幸的是,Ruby的sort不稳定。但请参阅this question了解解决方法。

答案 2 :(得分:0)

# Sort on each entry in `ticket_columns`, starting with the first column, then second, etc.
# Complex sorts are supported. If the first element in each `ticket_columns` is a true/false
# boolean (specifying if an ascending sort should be used), then it is sorted that way. 
# If omitted, it will sort all ascending.
def _subsort_columns(*ticket_columns)
  # Is the first element of every `ticket_column` a boolean?
  complex_sort = ticket_columns.all? { |e| [TrueClass, FalseClass].include? e[0].class }
  if complex_sort
    data = ticket_columns.transpose
    sort_directions = data.first
    column_data = data[1..-1].flatten 1
    sorted = column_data.transpose.sort do |cmp_first, cmp_last|
      cmp_which = sort_directions.map { |b| b ? cmp_first : cmp_last }
      cmp_these = sort_directions.map { |b| b ? cmp_last : cmp_first }
      cmp_left, cmp_right = [], []
      cmp_which.each_with_index { |e, i| cmp_left << e[i] }
      cmp_these.each_with_index { |e, i| cmp_right << e[i] }
      cmp_left <=> cmp_right
    end
    sorted
  else
    ticket_columns.transpose.sort
  end
end