[ruby] 4 개의 그룹으로 배열 요소를 작업하는 루비

각 요소를 처리해야 할 때 루비 스크립트 배열이 있습니다.

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

그러나 리소스 제한으로 인해 한 번에 네 가지 요소가 더 이상 처리되지 않으면 스크립트가 최적의 방식으로 작동합니다.

아니 나는 각 루프를 덤프하고 변수를 사용하여 4 요소를 계산 한 다음 기다릴 수 있다는 것을 알고 있지만 더 멋진 루비 방법이 있습니까?



답변

배열에 대해 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]

그래서 당신은 다음과 같은 것을 시도 할 수 있습니다.

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

그래도 필요한 것이 아닐 수도 있습니다. 오전 3시 이후에 일어나서 잠을 몇 시간 밖에 안 잤습니다. : /


답변

내가 올바르게 읽으면 한 번에 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 }


답변

다음 변형이 “4 개의 요소를 계산하는 변수”를 사용하는 것으로 간주되는지 또는 멋진 것으로 간주 될 수 있는지 확실하지 않지만 4 개 요소보다 크지 않은 크기의 조각으로 배열을 제공합니다.

x = (1..10).to_a
0.step(x.size - 1, 4) do |i|
    # Choose one
    p x.slice(i, 4)
    p x[i, 4]
end


답변

레일에서는 더 읽기 쉬운 형식을 사용할 수 있습니다. in_groups_of

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

결과:

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

에서 false를 지정 했으므로 마지막 행에는 3 개의 요소 만 in_group_of있습니다. nil 또는 다른 값을 원하면 false를 해당 값으로 바꿀 수 있습니다.


답변

예,하지만 몇 가지 메서드 재정의를 수행해야합니다. 일반적인 접근 방식은 Array다음과 같이 ‘/’를 재정의하는 것입니다.

class Array
  def / len
    a = []
    each_with_index do |x,i|
      a << [] if i % len == 0
      a.last << x
    end
    a
  end
end

정의 된대로 이제 다음을 쉽게 수행 할 수 있습니다.

foo = [1,2,3,4,5,6]
foo / 2
# Result is [[1,2], [3,4], [5,6]]


답변