2014-05-13 3 views
1

Jenkins에서 n 개의 항목 배열을 포함하는 json을 가져 오는 루비 코드가 있습니다. 내가 원하는 항목은 내가 너무루비는 특정 키의 해시/배열을 딥 검색 할 수 있습니까?

actions.each do |action| 
    if action["lastBuiltRevision"] 
     lastSuccessfulRev = action["lastBuiltRevision"]["SHA1"] 
     break 
    end 
end 

같은 배열을 통해 루프를 할 수 있습니다 알고 있지만 이들은 매우 투박하고 루비와 함께 작업 할 때 나는 보통 느끼는 마법없는 느낌 "lastBuiltRevision"

라는 키가 .

나는 약 1 주일 만에 땜질을 해왔다. 나는 이것을 더 쉽고 빠르게 만들기 위해 뭔가를 놓칠지도 모른다.

그런 것이 있습니까? 아니면 내가 할 수있는 수동 반복인가?

내가 가지처럼 뭔가를 바라고

lastSuccessfulRev = action.match("lastBuildRevision/SHA1") 

답변

3

하는 Enumerable#find 사용 :

actions = [ 
    {'dummy' => true }, 
    {'dummy' => true }, 
    {'dummy' => true }, 
    {'lastBuiltRevision' => { "SHA1" => "123abc" }}, 
    {'dummy' => true }, 
] 
actions.find { |h| 
    h.has_key? 'lastBuiltRevision' 
}['lastBuiltRevision']['SHA1'] 
# => "123abc" 

UPDATE

위의 코드는 일치 항목이없는 경우 NoMethodError을 표시합니다. 예외를 원하지 않으면 follow 코드를 사용하십시오.

rev = actions.find { |h| h.has_key? 'lastBuiltRevision' } 
rev = rev['lastBuiltRevision']['SHA1'] if rev 
+1

... 하나도 존재하지 않는다면? –

+0

그러면 nil이 올바르게 반환됩니까? 나는 이미 다른 목적을 위해 코드에서이 값을 검사하지 않고있다. – Weston

+2

@Kronusdark, Enumerable # find는 일치하는 항목이 없으면'nil'을 반환하기 때문에 예외 'NoMethodError'가 발생합니다. – falsetru

1

시도 :

action.map { |a| a["lastBuiltRevision"] }.compact.map { |lb| lb["SHA1"] }.first 
+0

내가 좋아하는 것보다 약간 wordier,하지만 작동하고 (적어도 외관에서) 덜 깨어나입니다 – Weston

+2

@Kronusdark 만이 검사하고 당신이 필요로하는 동안 모든 작업을 처리 하나,'find'가 더 좋은 방법입니다. –

1

여기라고 매개 변수 ifnone 소요 Enumerable#find의 형태를 활용, 그것을 할 수있는 또 다른 방법, 그리고 find의 블록 true을 평가하지 않을 경우 반환 값이 돌아왔다.

키를 찾을 수없는 경우 nil을 반환하는 것으로 가정합니다.

코드

def look_for(actions, k1, k2) 
    actions.find(->{{k1=>{}}}) { |e| e.key?(k1) }[k1][k2] 
end 

look_for(actions, 'lastBuiltRevision', 'SHA1') #=> "123abc" 
look_for(actions, 'cats', 'SHA1')    #=> nil 
look_for(actions, 'lastBuiltRevision', 'cats') #=> nil 

내가 findifnone 매개 변수 람다를했습니다

설명 :

l = ->{{k1=>{}}} 

그래서를 :

k1 = "cats" 
h = l.call #=> {"cats"=>{}} 
h[k1]['SHA1'] #=> {}['SHA1'] 
       #=> nil 
관련 문제