코드
require 'json'
def cross_tab(json, range_mins)
JSON.parse(json)["tickets"].each_with_object(Hash.new(0)) do |g,h|
diff = g["etime"]-g["ctime"]
h[[g["queue"], range_mins.rindex { |mn| mn <= diff }]] += 1
end
end
예
json = '{"ticketCount": 6,
"tickets": [
{"ctime": 1506061704724, "etime": 1506083304724, "queue": "low"},
{"ctime": 1506127874782, "etime": 1506149474782, "queue": "low"},
{"ctime": 1506283760321, "etime": 1506283760322, "queue": "high"},
{"ctime": 1506236363281, "etime": 1506257963281, "queue": "high"},
{"ctime": 1506283655948, "etime": 1506283667938, "queue": "low"},
{"ctime": 1506283781894, "etime": 1506284781894, "queue": "medium"}
]
}'
range_mins = [0, 10, 30, 60, 300].map { |n| 60000 * n }
#=> [0, 600_000, 1_800_000, 3_600_000, 18_000_000]
h = cross_tab(json, range_mins)
#=> {["low", 4]=>2, ["high", 0]=>1, ["high", 4]=>1, ["low", 0]=>1, ["medium", 1]=>1}
h[["high", 4]]
#=> 1
h[["low", 3]]
#=> 0
h
가 0
없이 키 ["low", 3]
기본값을 가지고 있기 때문에 두 번째 결과를 얻는다.
이제 우리는 다음과 같이 크로스 탭 (또는 크로스 집계 또는 비상 테이블)의 내용을 구성 할 수 있습니다.
row_map = { 0=>"low", 1=>"medium", 2=>"high" }
tbl = Array.new(row_map.size) { |i|
Array.new(range_mins.size) { |j| h[[row_map[i], j]] } }
#=> [[1, 0, 0, 0, 2],
# [0, 1, 0, 0, 0],
# [1, 0, 0, 0, 1]]
행은 (열) 레이블은 우리가 양자 택일 json
에서 row_map
을 계산할 수 row_map
(range_mins
)
에서 얻을 수 있습니다.
JSON.parse(json)["tickets"].map { |h| h["queue"] }.uniq.
map.with_index { |queue, i| [i, queue] }.to_h
#=> {0=>"low", 1=>"high", 2=>"medium"}
그러나 이것은 우리가 테이블의 행의 순서를 지정하거나
"queue"
의 값의 일부 테이블을 생성 할 수 없습니다.
설명
있어서 해시 대한 디폴트 값 (여기서는 0
) 인수를 취하는 클래스 Hash::new 방법의 형태를 사용한다. 즉, h = Hash.new(0)
및 h
에 k
키가없는 경우 h[k]
이 기본값을 반환합니다.
이렇게 정의 된 해시는 이라고도하며 으로 계산되며 일반적으로 사용되며 계산 방식이 h[k] +=1
인 경우 여기에서 사용됩니다.루비는이를 볼 때, 그녀가 제일 먼저 0
, h
기본 값으로 변환됩니다 평등 (방법 Hash#[])의 오른쪽에 키 k
, h[k]
이없는 경우
h[k] = h[k] + 1
로 확장하다 . 이 표현식이 동일한 키 k
에 대해 실행될 때마다 오른쪽의 h[k]
은 현재 값 k
을 반환합니다 (즉, 기본값은 적용되지 않습니다). (왼쪽에있는 h[k]
은 기본값과 아무 관계가없는 Hash#[]= 메서드입니다.)
다음 단계를 따르십시오. 블록에 전달
h = JSON.parse(json)
#=> {"ticketCount"=>6,
# "tickets"=>[
# {"ctime"=>1506061704724, "etime"=>1506083304724, "queue"=>"low"},
# {"ctime"=>1506127874782, "etime"=>1506149474782, "queue"=>"low"},
# {"ctime"=>1506283760321, "etime"=>1506283760322, "queue"=>"high"},
# {"ctime"=>1506236363281, "etime"=>1506257963281, "queue"=>"high"},
# {"ctime"=>1506283655948, "etime"=>1506283667938, "queue"=>"low"},
# {"ctime"=>1506283781894, "etime"=>1506284781894, "queue"=>"medium"}
# ]
# }
a = h["tickets"]
#=> [{"ctime"=>1506061704724, "etime"=>1506083304724, "queue"=>"low"},
# {"ctime"=>1506127874782, "etime"=>1506149474782, "queue"=>"low"},
# {"ctime"=>1506283760321, "etime"=>1506283760322, "queue"=>"high"},
# {"ctime"=>1506236363281, "etime"=>1506257963281, "queue"=>"high"},
# {"ctime"=>1506283655948, "etime"=>1506283667938, "queue"=>"low"},
# {"ctime"=>1506283781894, "etime"=>1506284781894, "queue"=>"medium"}]
e = a.each_with_object(Hash.new(0))
#=> #<Enumerator: [
# {"ctime"=>1506061704724, "etime"=>1506083304724, "queue"=>"low"},
# {"ctime"=>1506127874782, "etime"=>1506149474782, "queue"=>"low"},
# ...
# {"ctime"=>1506283781894, "etime"=>1506284781894, "queue"=>"medium"}
# ]:each_with_object({})>
제 1 엘리먼트 소자를 열거함으로써 생성
는, 상기 블록은 그 변수의 값과 동일하게 설정되며, 상기 블록 계산이 수행된다.
는
g, h = e.next
# => [{"ctime"=>1506061704724, "etime"=>1506083304724, "queue"=>"low"}, {}]
g #=> {"ctime"=>1506061704724, "etime"=>1506083304724, "queue"=>"low"}
h #=> {}
f = g["queue"]
#=> "low"
diff = g["etime"]-g["ctime"]
#=> 1506083304724 - 1506061704724 => 21600000
j = range_mins.rindex { |mn| mn <= diff }
#=> 4
이 range_mins[4] #=> 18_000_000
는 diff
(21_600_000
)`이하인 range_mins
의 최대 값 인 것을 나타내고있다. ,
k = [f, j]
#=> ["low", 4]
h[k] += 1
#=> 1
h #=> {["low", 4]=>1}
다음 값을 계속하는 것은 다음 열거 e
하여 블록으로 전달된다.
g, h = e.next
#=> [{"ctime"=>1506127874782, "etime"=>1506149474782, "queue"=>"low"},
# {["low", 4]=>1}]
g #=> {"ctime"=>1506127874782, "etime"=>1506149474782, "queue"=>"low"}
h #=> {["low", 4]=>1}
f = g["queue"]
#=> "low"
diff = g["etime"]-g["ctime"]
#=> 1506149474782 - 1506127874782 => 21600000
j = range_mins.rindex { |mn| mn <= diff }
#=> 4
k = [f, j]
#=> ["low", 4]
h[k] += 1
#=> 2
h #=> {["low", 4]=>2}
나머지 단계는 유사합니다.
루비에서는 일반적으로 결과를 합계로 나누기 위해'group_by'와 다른 것들을 사용합니다. – tadman