ruby以四个为一组的数组元素工作

Eli*_*Eli 70 ruby

当每个元素需要处理时,我有一个ruby脚本数组:

threads = []
elemets.each do  |element|
    threads.push(Thread.new{process(element)}}
end
threads.each { |aThread|  aThread.join }
Run Code Online (Sandbox Code Playgroud)

然而,由于资源限制,如果一次不再处理四个元素,则脚本以最佳方式工作.

不,我知道我可以转储每个循环并使用一个变量来计算4个元素,然后等待,但是有一个更酷的红宝石方式吗?

小智 149

您可以以4个为一组枚举数组:

>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].each_slice(4) {|a| p a}
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
Run Code Online (Sandbox Code Playgroud)

所以你可以尝试类似的东西

elements.each_slice(4) do | batch |
    batch.each do | element |
        threads.push(Thread.new{process(element)}}

    end
    (do stuff to check to see if the threads are done, otherwise wait )
end
Run Code Online (Sandbox Code Playgroud)

它可能不是你所需要的 - 但是我从凌晨3点开始起床,我只睡了几个小时.:/

  • @Rilindo:这太棒了!修改了两行,我很高兴。谢谢。 (2认同)
  • 当我的任务需要不同的时间来处理时,下面的(我的)解决方案应该更有效.此解决方案假设每个线程将花费相同的时间来处理4个元素的列表. (2认同)
  • 我想我刚刚再次爱上了Ruby :) (2认同)

And*_*icz 21

如果我读了你,你想要一次处理不超过4个线程.

听起来像你应该只启动4个线程,让它们都从共享队列(标准线程库的一部分)读取来处理元素.

当队列为空时,您可以让线程结束.

将数组切成4个相等的数组,并让每个线程处理1/4的元素假定每个元素在同一时间处理.如果有些人花费的时间比其他人长,那么你的一些线程会提前完成.

使用队列,在共享队列为空之前没有线程停止,因此我认为这是一种更有效的解决方案.

这是一个基于您的代码的工作程序来演示:

require 'thread'

elements = [1,2,3,4,5,6,7,8,9,10]

def process(element)
    puts "working on #{element}"
    sleep rand * 10
end

queue = Queue.new
elements.each{|e| queue << e }

threads = []
4.times do
    threads << Thread.new do
      while (e = queue.pop(true) rescue nil)
        process(e)
      end
    end
end

threads.each {|t| t.join }
Run Code Online (Sandbox Code Playgroud)


Imr*_*mad 14

rails(不是Ruby)中,可以使用更易读的形式in_groups_of

arr= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
arr.in_groups_of(4, false) {|a| p a}
Run Code Online (Sandbox Code Playgroud)

结果:

[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11]
Run Code Online (Sandbox Code Playgroud)

最后一行只有 3 个元素,因为我们在 中指定了 false 作为第二个参数in_group_of。如果您想要 nil 或任何其他值,您可以将 false 替换为该值。

  • `in_groups_of` 是一种 Rails 方法,不适用于普通 ruby (3认同)