2012-02-18 5 views
45

나는 Ruby Koans tutorial series를 통과했다 : assert_equals에서루비 해시에서 셔블 (<<) 연산자는 어떻게 작동합니까? 내가 <code>about_hashes.rb</code>이에 왔을 때

def test_default_value_is_the_same_object 
    hash = Hash.new([]) 

    hash[:one] << "uno" 
    hash[:two] << "dos" 

    assert_equal ["uno", "dos"], hash[:one] 
    assert_equal ["uno", "dos"], hash[:two] 
    assert_equal ["uno", "dos"], hash[:three] 

    assert_equal true, hash[:one].object_id == hash[:two].object_id 
end 

값은, 튜토리얼 기대했던 사실이다. 하지만 << 운영자와 = 운영자를 사용하는 경우의 차이점을 이해할 수 없습니까?

  • hash[:one]["uno"]
  • hash[:two]["dos"]
  • hash[:three] 내 예상이 틀린 이유를 []

누군가가 설명해 주시겠습니까 될 것 같습니다

내 기대는 것이 었습니다?

+4

재밌네, 그게 내가 예상 한거야. 그렇다면 산은 다시 단지 산이였습니다. –

답변

52

hash = Hash.new([])을 수행 할 때 모든 키의 기본값이 정확히 동일한 Array 인스턴스 인 해시가 생성됩니다. 따라서 존재하지 않는 키에 액세스 할 때마다 동일한 Array가 반환됩니다. 당신은 키 당 하나 개의 배열을 원하는 경우

h = Hash.new([]) 
h[:foo].object_id # => 12215540 
h[:bar].object_id # => 12215540 

, 당신은 Hash.new의 블록 구문을 사용해야합니다 :

h = Hash.new { |h, k| h[k] = [] } 
h[:foo].object_id # => 7791280 
h[:bar].object_id # => 7790760 

편집 :는 또한 Gazler가 #<< 방법에 관하여 말해야하는 것을보고 당신이 실제로 그것을 불러오는 대상.

+1

+1은 object_id를 사용하여 참조를 보여준다. – Gazler

+0

감사합니다. 따라서 원래의 빈 배열은 기본값으로 저장되는 객체입니다. 그리고 우리는'nil' 대신 원래의 객체를 되찾고 있습니다. 산뜻한! 두 응답 (당신과 @ Gazler에 의해) 모두 upvoting지만, 이것을 받아 주셔서 감사합니다. – bits

58

약간 혼란스러워합니다. 우선 해시에는 << 메서드가 없으므로 예제의 메서드가 배열에 있습니다.

코드가 오류가 발생하지 않는 이유는 생성자를 통해 해시에 기본값을 전달하기 때문입니다. http://ruby-doc.org/core-1.9.3/Hash.html#method-c-new

hash = Hash.new([]) 

이것은 키가 존재하지 않는 경우,이 배열을 반환 할 것을 의미한다. 다음 코드를 실행하는 경우

hash = {} 
hash[:one] << "uno" 

그런 다음 정의되지 않은 메서드 오류가 발생합니다.

당신의 예에 따라서

, 무엇을 실제로 일어나고있는 것은 :이 값에 대한 참조를 저장하기 때문에

hash = Hash.new([]) 

hash[:one] << "uno" #hash[:one] does not exist so return an array and push "uno" 
hash[:two] << "dos" #hash[:two] does not exist, so return the array ["uno"] and push "dos" 

가 하나 개의 요소는 예상을했던 것으로서마다 배열을 반환하지 않는 이유입니다 당신은 생성자를 통과합니다. 요소가 푸시 될 때마다 초기 배열을 수정한다는 것을 의미합니다.

+2

감사합니다. @ gazler. 이것은 그것을 명확하게하는 것을 도왔다. – bits

+1

고맙습니다. – Etch

+4

이 답변을 받아 들여야합니다. 훨씬 더 명확한 설명.감사합니다 –

관련 문제