在ruby中按批次排序数组

Jua*_*que 6 ruby sorting

很抱歉,如果之前已经询问过,我不确定如何搜索它,我搜索的内容不会产生任何有用的答案.

这是我的问题,我有一个框架,基本上管理将提交到PBS集群的作业,每个作业都需要从输入文件中读取.我们处于这样一种情况,即我们有超过5k个需要运行的作业,并且有批次,比如说,从不同的文件中读取的〜30个,但其余的从另一个作业正在读取的文件中读取.

这可以很容易地处理(尽管不是最好的解决方案,也许是我们所拥有的时间刻度中最快的一个),因为它能够通过ID对作业列表进行排序,这基本上意味着它将从哪个文件读取,即我会喜欢这样排序一个数组

a = [1,1,1,2,2,2,3,3,3,4,4,4]
Run Code Online (Sandbox Code Playgroud)

a = [1,2,3,4,1,2,3,4,1,2,3,4]
Run Code Online (Sandbox Code Playgroud)

有没有办法在红宝石中实现这样的排序?我可以想到一个算法购买可能它已经完成,有人知道答案.

谢谢!

Eri*_*nil 7

感谢@ sagarpandya82最初的想法和@Cary Swoveland寻找错误!

要么使用2种方法:

def safe_transpose_and_flatten(array)
  l = array.map(&:length).max
  array.map{|e| e.values_at(0...l)}.transpose.flatten.compact
end

def sort_by_batches(array)
  safe_transpose_and_flatten(array.sort.group_by{|i| i}.values)
end
Run Code Online (Sandbox Code Playgroud)

或者这个单行(为了相对可读性而分成多行):

def sort_by_batches(array)
  array.group_by{|i| i }.values                  # Chunks of equal values,
       .sort_by{|v| -v.size }                    # sorted by decreasing length,
       .reduce(&:zip)                            # transposed,
       .map{|r| r.flatten.compact.sort }.flatten # flattened and sorted
end
Run Code Online (Sandbox Code Playgroud)

a = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]
sort_by_batches(a) # => [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]

a = [1, 1, 3, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 1, 1]
sort_by_batches(a) # => [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4, 1, 3]

a = [1,2,2,3,3,3]
sort_by_batches(a) # => [1, 2, 3, 2, 3, 3]
Run Code Online (Sandbox Code Playgroud)

脚步

以下是第二个数组的步骤:

[1, 1, 3, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 1, 1] # input
{1=>[1, 1, 1, 1], 3=>[3, 3, 3, 3], 2=>[2, 2, 2], 4=>[4, 4, 4], 5=>[5]} # group_by
[[1, 1, 1, 1], [3, 3, 3, 3], [2, 2, 2], [4, 4, 4], [5]] # values
[[1, 1, 1, 1], [3, 3, 3, 3], [2, 2, 2], [4, 4, 4], [5]] # sort_by -length
[[[[[1, 3], 2], 4], 5], [[[[1, 3], 2], 4], nil], [[[[1, 3], 2], 4], nil], [[[[1, 3], nil], nil], nil]] # zip
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4], [1, 3]] # map(&:flatten) and compact
[1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4, 1, 3] # flatten
Run Code Online (Sandbox Code Playgroud)

.reduce(&:zip).map(&:flatten).compact 最初被用作一个所谓的安全转置,但是当第一个阵列小于其他阵列时,它不起作用.

第一种方法使用答案进行转置,单线程在使用前通过减少长度对数组进行排序zip.

应用于Job类

这是一个非常基本的Job类作为示例:

class Job
  attr_reader :id
  def initialize(id)
    @id = id
  end

  def self.sort_by_batches(jobs)
    safe_transpose_and_flatten(jobs.sort_by{|j| j.id}.group_by{|j| j.id}.values)
  end

  def to_s
    "Job %d" % id
  end
end

jobs = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4].map{|i| Job.new(i)}
Job.sort_by_batches(jobs)
Run Code Online (Sandbox Code Playgroud)

它输出:

Job 1
Job 2
Job 3
Job 4
Job 1
Job 2
Job 3
Job 4
Job 1
Job 2
Job 3
Job 4
Run Code Online (Sandbox Code Playgroud)