2014-06-12 3 views
0

간격이라는 배열 배열이 있습니다. 각 해시 (start_ts 및 stop_ts)에 두 개의 키/값 쌍을 추가하여 해시 배열을 만들려고합니다.루비 : 각 루프의 배열에 해시 추가.

require 'date' 
date = '2014-06-12' 
totalhash = Hash.new 
totalarray = Array.new 
payload2 = Array.new 
totals = Array.new 

intervals = [["Current", 0, 9999], 
      ["1 to 4", -4, -1], 
      ["5 to 15", -15, -5], 
      ["16 to 30", -30, -16], 
      ["31 to 60", -60, -31], 
      ["61 to 90", -90, -61], 
      ["91+", -9999, -91]] 

intervals.each do |int| 
    label, start, stop = int 
    # Parse date and then convert to UNIX epoch (.to_time.to_i chain) 
    start_ts = (Date.parse("#{date}") + start).to_time.to_i 
    stop_ts = (Date.parse("#{date}") + stop).to_time.to_i 

    totalhash[:label]    = label 
    totalhash[:start]    = start 
    totalhash[:stop]    = stop 
    totalhash[:start_ts]   = start_ts 
    totalhash[:stop_ts]   = stop_ts 

    totalarray << totalhash 
    totals = totalarray.reduce Hash.new, :merge 
    puts totals 
    puts 'totals size: ' + totals.size.to_s 
end 

최종 결과는 7 가지 해시의 배열이어야합니다. 현재 어레이 totalarray는 추가되는 것과는 반대로 각 패스에서 덮어 쓰여진 것처럼 보입니다.

내가 뭘 잘못하고있어. 감사.

+0

이 코드를 어떻게 실행 했습니까? 구문 오류가 너무 많습니다. –

+0

@ArupRakshit 구문 오류가 하나 있습니다.'intervals.each do | int | do (두 번 두 번). –

+0

나는 '날짜'를 요구하고 불쾌한 두 번째를 제거했습니다. 미안합니다. – user3707736

답변

1

어레이의 1 대 1 출력을 원하면 map을 사용하십시오. 모든 중간 변수에 대한 필요성을 줄입니다.

# Parse date outside the loop as per @Uri's comment 
day = Date.parse(date) 

t = intervals.map do |interval| 
     label, start, stop = interval 
     { 
     label: label, 
     start: start, 
     stop:  stop, 
     start_ts: (day + start).to_time.to_i, 
     stop_ts: (day + stop).to_time.to_i 
     } 
    end 

이렇게하면 원하는 7 해시 배열이됩니다.

단일 해시 출력의 경우 : 귀하의 reduce 라인이 원인입니다. 네가 뭘하려고하는지 모르겠다.

myArray = [['cow','moo'],['dog','woof'],['duck','quack'],['fox','?']] 

myArray.collect! do |animal| 
    animal = {animal[0]=>animal[1]} 
end 

puts myArray.inspect 

내가 여기 당신의 사용에 대해 언급 할 reduce 또는 inject 충분히 익숙하지 않다 :

+0

그리고 아마도 변수 간격을 제거하십시오 ... –

+2

그리고 루프 밖에서 한 번 날짜를 구문 분석해야합니다 ... –

+0

이들은 모두 좋은 답변이지만 나에게 분명히 받아 들였습니다. 고마워, 마크. – user3707736

0

이 :

totalarray << totalhash 

totalhash을 복사하지 않습니다, 그것은 단지 totalarray의 말에 대한 참조를 추가합니다. 그것은 더 많은 의미 말을 만들 것입니다 :

totalarray << { 
    # build the Hash inline right here 
} 

코드는 totalarray에서 정확히 같은 해시에 intervals.length 참조로 끝납니다. 그런 다음 reduce이 해시를 자체로 병합합니다. 그러면 해시가 유용하지 않습니다. 실제로 totals = totalarray.reduce Hash.new, :mergetotalarray이 제대로 구축 되더라도 아무런 도움이되지 않습니다. 단지 totals = totalarray.last이라고 말하면서 같은 결과를 얻을 수 있습니다.

0

나는 보통 이런 종류의 물건이 방법을한다.

require 'date' 
date = '2014-06-12' 
#totalhash = Hash.new 
totalarray = Array.new 
payload2 = Array.new 
totals = Array.new 

intervals = [["Current", 0, 9999], 
     ["1 to 4", -4, -1], 
     ["5 to 15", -15, -5], 
     ["16 to 30", -30, -16], 
     ["31 to 60", -60, -31], 
     ["61 to 90", -90, -61], 
     ["91+", -9999, -91]] 

intervals.each do |int| 
    totalhash = Hash.new #moved your hash creation here, in the iteration 
    label, start, stop = int 
    # Parse date and then convert to UNIX epoch (.to_time.to_i chain) 
    start_ts = (Date.parse("#{date}") + start).to_time.to_i 
    stop_ts = (Date.parse("#{date}") + stop).to_time.to_i 

    totalhash[:label]    = label 
    totalhash[:start]    = start 
    totalhash[:stop]    = stop 
    totalhash[:start_ts]   = start_ts 
    totalhash[:stop_ts]   = stop_ts 

    totalarray << totalhash 
    #totals = totalarray.reduce Hash.new, :merge 
    #puts totals 
    #puts 'totals size: ' + totals.size.to_s 
end 

puts totalarray.inspect #see the array object as is using 'inspect' 

~

0

나는 당신이 당신의 데이터 구조를 변경하는 것을 고려 제안 :하지만 여기 당신이 원하는 것을 생각 원래 코드의 편집 된 버전입니다. 나는 각 해시의 신기원 이후 계산 된 시간을 포함하는 것이 현명하다고 생각하지 않는다. 예를 들어

require 'date' 

date = Date.parse('2014-06-12') 
    #=> #<Date: 2014-06-12 ((2456821j,0s,0n),+0s,2299161j)> 

def start_stop_to_time(d, date) 
    (date + d).to_time.to_i 
end 

start_stop_to_time(-4, date) #=> 1402210800 

total_array

다음이 될 것이다 : 오히려, 단지 헬퍼 방법과 필요에 따라 그 값을 계산

total_array = [[:label, :start, :stop]].product(intervals) 
             .map { |k,v| k.zip(v).to_h } 
    #=> [{:label=> "Current", :start=> 0, :stop=>9999}, 
    # {:label=> "1 to 4", :start=> -4, :stop=> -1}, 
    # {:label=> "5 to 15", :start=> -15, :stop=> -5}, 
    # {:label=>"16 to 30", :start=> -30, :stop=> -16}, 
    # {:label=>"31 to 60", :start=> -60, :stop=> -31}, 
    # {:label=>"61 to 90", :start=> -90, :stop=> -61}, 
    # {:label=>  "91+", :start=>-9999, :stop=> -91}] 

나는 totals의 목적을 이해하지 않는다 , 나는 그것에 대해 논평 할 수 없다.