2014-02-24 3 views
1

collect!을 사용하여 해시 배열을 수정하려고합니다. 각 해시마다 1 개의 새 키/값을 추가하고 다른 키/값을 수정하고 싶습니다. 그러나 sub!을 사용하여 기존 해시 값을 수정하는 데 문제가 있습니다. 그것은 서브의 결과와 같은 하나의 배열 엔트리로 해쉬를 완전히 대체하는 것처럼 보입니다! 명령Ruby가 해시 배열을 수정하여 해시 배열에 추가합니다.

paths = [{:path=>"bin/ruby/file1", :tag=>"v_10"}, {:path=>"usr/name/subdir/file2", :tag=>"v_12"}] 

paths.collect! do |x| 
    x.merge(Hash[:file => x[:path].sub(/.*\//,"")]) # Grab file name 
    x[:path].sub!(/\/\w+$/,"")      # remove file name from path 
end 

결과 :
=> ["bin/ruby", "usr/name/subdir"]

원하는 결과 :
=> [{:path=>"bin/ruby", :tag=>"v_10", :file=>"file1"}, {:path=>"usr/name/subdir", :tag=>"v_12", :file=>"file2"}]

답변

2

당신은 collect! 싶지 않아, 당신은 each을 원한다. Collect는 각 블록의 출력에 입력 해시를 매핑하고 블록 출력은 .sub 호출의 결과입니다. 즉, 변형 된 :path 값의 편평한 배열을 얻습니다.

또한 단지 새로운 해시를 구축하고 병합하지는 않고 않고 직접 키 :file을 설정할 수 있습니다

paths = [{:path=>"bin/ruby/file1", :tag=>"v_10"}, {:path=>"usr/name/subdir/file2", :tag=>"v_12"}] 

paths.each do |x| 
    x[:file] = x[:path].sub(/.*\//, '') 
    x[:path].sub!(/\/\w+$/,"")      # remove file name from path 
end 

puts paths.inspect # [{:path=>"bin/ruby", :tag=>"v_10", :file=>"file1"}, {:path=>"usr/name/subdir", :tag=>"v_12", :file=>"file2"}] 
+0

'수집'하지'collect'!. 'collect'는 괜찮 았지만 (merge 대신 merge!를 사용했을 것입니다.) 약간 무의미했습니다. –

+0

@muistooshort 어느 쪽의 옵션이 잘못 되었습니까? 그는 하나의 값 x (: path)를 반환했습니다./\/\ w + $ /, "") 블록 – meagar

+0

meagar에서 내 코드가 작동하지 않는 이유에 대한 설명에 감사드립니다. 나는 '각자'로 제자리에서 수정할 수 없다는 인상을 받았다. (그러므로'수집 '을 시도한 이유). 'x [: file] '을 어떻게 만들 수 있습니까? 배열 항목이 해시를 가리키고 그 포인터가 실제로 변경되지 않기 때문에 (즉'each'가 작동합니까?)? –

1

기능 스타일 버전

paths.map do |path| 
    parts = path[:path].split('/'); 
    { 
    :path => parts.first(parts.length - 1).join('/'), 
    :tag => path[:tag], 
    :file => parts.last 
    } 
end