루비

2012-03-14 9 views
4

다른 해시에 해시를 변환 나는 문자열루비

내가 키가 다시 키 또 다른 해시로 변환 할
navigable_objects = { 'Dashboard' => root_path, 
         'Timesheets' => timesheets_path, 
         'Clients' => clients_path, 
         'Projects' => projects_path, 
        } 

의 해시를 가지고 있지만 값 중 하나를 문자열 '활성'입니다 현재 컨트롤러 이름에 키가 포함되어 있는지 여부에 따라 빈 문자열을 반환합니다.

예를 들어 현재 컨트롤러 이름이 "ClientsController"라고 가정 해 봅시다. 내가 가야 결과는 다음과 같습니다

여기
{ 'Dashboard' => '', 
    'Timesheets' => '', 
    'Clients' => 'active', 
    'Projects' => '' 
} 

나는 현재 그 일을하고 방법 :

active = {} 

navigable_objects.each do |name, path| 
    active[name] = (controller.controller_name.include?(name)) ? 'active' : '') 
end 

나는이 작동하는 동안, 아마도 사용하여, 루비이 할 수있는 더 좋은 방법이 있다고 생각 inject 또는 each_with_objects?

+0

나는 다른 솔루션 (게시 된 모든 것들은 지금까지 훌륭함)이 있지만, 원래 당신이 그랬던 것처럼 특별히 잘못된 것은 없음을 지적하고 싶습니다. –

+0

나는 나를 가장 괴롭히는 것은 맨 위에있는 해쉬 선언이고, 여러분의 each_with_objects 솔루션은 그것을 거의 해결한다고 생각합니다! – link664

답변

3

참고 : 이미 대답했지만 특정 상황에 더 좋기 때문에 이것을 별도의 답변으로 게시하겠습니다. 그러나 다른 답변은 여전히 ​​고유 한 장점이 있습니다.전혀 해시 값을 사용하지 않는 때문에

, 당신은 each_with_object 사용할 수 있습니다 더 자세하게

navigable_objects.keys.each_with_object({}) { |k,h| h[k] = controller.controller_name.include?(k) ? 'active' : '' } 

또는 :

new_hash = navigable_objects.keys.each_with_object({}) do |key, hash| 
    hash[key] = controller.controller_name.include?(key) ? 'active' : '' 
end 

당신의 결과를 기반으로 한 경우 그 값도 그렇습니다. 그러면 다른 해결책이 효과가있을 것입니다.

5

업데이트 : 귀하의 상황에 맞는 것으로 생각되는 다른 답변을 게시했습니다. 나는 비슷한 문제에 대해 독자적으로 장점을 가지고 있기 때문에 편집되지 않은 상태로 남겨두고있다. 당신은 블록에 입력으로 키와 값 쌍을 가져 해시에 map를 실행할 수 있습니다

Hash[*navigable_objects.map{ |k,v| [k, controller.controller_name.include?(k) ? 'active' : ''] }.flatten] 

:

는 여기에 내가 그것을하려는 방법입니다. 그런 다음 키/값 쌍을 출력으로 배열로 구성 할 수 있습니다. 마지막으로 실행중인 Hash[*key_value_pairs.flatten]은 해시로 되돌리기위한 멋진 트릭입니다. 이 작업은 해시 (Hash[1, 2, 3, 4] =>{ 1 => 2, 3 => 4 })를 생성하기 위해 Hash[] 생성자에 인수 배열을 전달할 수 있기 때문에 가능합니다. flatten은 키 값 쌍을 배열로 변환하고 * 연산자는 배열을 인수 목록으로 바꿉니다.

key_value_pairs = navigable_objects.map do |key, value| 
    new_value = controller.controller_name.include?(k) ? 'active' : '' 
    [key, new_value] 
end 

new_hash = Hash[*key_value_pairs.flatten] 

업데이트 : 이것은 위의 루비 1.8과 호환되는

여기에 당신이 더 명확하게 무슨 일이 일어나고 있는지보고 싶은 경우에 자세한 버전입니다. 1.9에서

당신이 * 필요하거나 해시 [] 키 - 값의 배열을 쌍

사용되기 때문에이 작업을 수행 할 수있는 많은 방법에는 여러 가지가 있습니다
+3

1.9에서는''Hash []'로'*'또는'flatten'을 사용할 필요가 없습니다 (http://ruby-doc.org/core-1.9.3/Hash.html#method-c-5B -5D)는 키 - 값 배열 쌍을 사용합니다. –

1

평평하지 않습니다 앤드류는 의견에서 지적 . 이것은 내가하는 방식 일뿐입니다. 만약 해시 inject를 호출 할 때, 블록은 상기 키와를 상기 제 1 요소 배열 (이 경우 해시 투입)하면에 주입되는 것을 전달

inject

active = navigable_objects.inject({}) do |h, obj| 
    h[obj[0]] = controller.controller_name.include?(obj[0]) ? 'active' : '' 
    h 
end 

으로 마지막 요소는 값입니다.

+0

[ 'each_with_object'] (http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-each_with_object)는 모든 해시 참조를 잘못 반환 할 필요가 없으므로 여기서 더 좋습니다. time':)' –

+0

'each_with_object'를 사용하지 않았습니다.'h.merge ({key => val})' – Kyle

+0

Nah; 'each_with_object'는 [더 많은 타이핑을하고'inject' (또는'tap')보다 느립니다.] (http://phrogz.net/tap-vs-each_with_object). – Phrogz

0

루비 2.0 이후, to_h가 :

navigable_objects.map do |name, path| 
    [name, controller.controller_name.include?(name)) ? 'active' : ''] 
end.to_h 

나는 그것은 매우 효율적이라고 생각하지 않지만, 작은 해시 것이 우아한 방법입니다.