루비에서 해시를 복사하려면 어떻게 해야 합니까?
저는 제가 약간 루비 초보자라는 것을 인정하겠습니다. (지금은 갈퀴 대본을 쓰고 있습니다.)대부분의 언어에서 복사 생성자는 쉽게 찾을 수 있습니다.30분 동안 검색해도 루비에서 발견되지 않았습니다.원본 인스턴스에 영향을 주지 않고 수정할 수 있도록 해시 복사본을 만들고 싶습니다.
예상되는 몇 가지 방법은 의도한 대로 작동하지 않습니다.
h0 = { "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
h1=Hash.new(h0)
h2=h1.to_hash
그동안, 저는 이 무례한 해결책에 의지해 왔습니다.
def copyhash(inputhash)
h = Hash.new
inputhash.each do |pair|
h.store(pair[0], pair[1])
end
return h
end
이 방법은 Ruby가 기본으로 제공하는 얕은 복사 방법입니다.
h0 = {"John" => "Adams", "Thomas" => "Jefferson"}
# => {"John"=>"Adams", "Thomas"=>"Jefferson"}
h1 = h0.clone
# => {"John"=>"Adams", "Thomas"=>"Jefferson"}
h1["John"] = "Smith"
# => "Smith"
h1
# => {"John"=>"Smith", "Thomas"=>"Jefferson"}
h0
# => {"John"=>"Adams", "Thomas"=>"Jefferson"}
동작이 재정의될 수 있습니다.
이 메서드에는 클래스별 동작이 있을 수 있습니다.만약 그렇다면, 그 행동은 아래에 문서화될 것입니다.
#initialize_copy
학급의 방식
다른 사람들이 지적했듯이,clone
할 것입니다.알아두시기 바랍니다.clone
해시의 복사본은 얕습니다.즉, 다음과 같습니다.
h1 = {:a => 'foo'}
h2 = h1.clone
h1[:a] << 'bar'
p h2 # => {:a=>"foobar"}
해시의 참조는 복사되지만 참조가 참조하는 개체는 복사되지 않습니다.
딥 카피를 원하는 경우:
def deep_copy(o)
Marshal.load(Marshal.dump(o))
end
h1 = {:a => 'foo'}
h2 = deep_copy(h1)
h1[:a] << 'bar'
p h2 # => {:a=>"foo"}
deep_copy
마샬링할 수 있는 모든 개체에 대해 작동합니다.대부분의 기본 제공 데이터 유형(Array, Hash, String 등)을 마샬링할 수 있습니다.
마셜링은 루비의 연재 이름입니다.Marshalling을 사용하면 객체가 참조하는 객체와 함께 일련의 바이트로 변환됩니다. 그런 다음 해당 바이트는 원본과 같은 다른 객체를 만드는 데 사용됩니다.
레일즈를 사용하는 경우 다음 작업을 수행할 수 있습니다.
h1 = h0.deep_dup
http://apidock.com/rails/Hash/deep_dup
해시는 기존 해시에서 새 해시를 생성할 수 있습니다.
irb(main):009:0> h1 = {1 => 2}
=> {1=>2}
irb(main):010:0> h2 = Hash[h1]
=> {1=>2}
irb(main):011:0> h1.object_id
=> 2150233660
irb(main):012:0> h2.object_id
=> 2150205060
신뢰할 수 없는 데이터를 역직렬화해야 하는 경우 JSON 또는 String, Array, Hash 등과 같은 단순한 '기본' 유형만 로드할 수 있는 다른 직렬화 형식을 사용합니다.
다음은 Ruby에서 JSON을 사용하여 복제하는 방법의 예입니다.
require "json"
original = {"John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
cloned = JSON.parse(JSON.generate(original))
# Modify original hash
original["John"] << ' Sandler'
p original
#=> {"John"=>"Adams Sandler", "Thomas"=>"Jefferson", "Johny"=>"Appleseed"}
# cloned remains intact as it was deep copied
p cloned
#=> {"John"=>"Adams", "Thomas"=>"Jefferson", "Johny"=>"Appleseed"}
저도 루비의 초보자인데 해시를 복제하는 과정에서 비슷한 문제에 직면했습니다.다음을 사용합니다.저는 이 방법의 속도에 대해 전혀 모릅니다.
copy_of_original_hash = Hash.new.merge(original_hash)
사용:
h1 = h0.clone
(혼란스럽게도, 다음에 대한 설명서clone
그렇다고 합니다initialize_copy
이를 재정의하는 방법이지만 해당 방법에 대한 링크는Hash
로 안내합니다.replace
대신...)
표준 복제 방법은 고정 상태를 유지하므로 새 개체가 원래 개체와 약간 다르도록 하려면(상태 비저장 프로그래밍을 좋아하는 경우) 원래 개체를 기반으로 새 불변 개체를 생성하는 데 적합하지 않습니다.
복제 속도가 느립니다.성능을 위해서는 아마도 빈 해시와 병합으로 시작해야 합니다.중첩된 해시의 경우를 포함하지 않습니다...
require 'benchmark'
def bench Benchmark.bm do |b|
test = {'a' => 1, 'b' => 2, 'c' => 3, 4 => 'd'}
b.report 'clone' do
1_000_000.times do |i|
h = test.clone
h['new'] = 5
end
end
b.report 'merge' do
1_000_000.times do |i|
h = {}
h['new'] = 5
h.merge! test
end
end
b.report 'inject' do
1_000_000.times do |i|
h = test.inject({}) do |n, (k, v)|
n[k] = v;
n
end
h['new'] = 5
end
end
end
end
벤치 사용자 시스템 총계(실제)클론 1.960000 0.080000 2.040000(2.029604)병합 1.690000 0.080000 1.7700 (1.767828)주입 3.160000 0.030000 3.1600(3.152627)
이는 특별한 경우이지만, 미리 정의된 해시를 가져와 복사본을 만드는 경우 해시를 반환하는 메서드를 만들 수 있습니다.
def johns
{ "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
end
h1 = johns
제가 가졌던 특별한 시나리오는 JSON-schema 해시 컬렉션을 가지고 있었습니다. 어떤 해시들은 다른 해시들을 쌓아올렸습니다.처음에 클래스 변수로 정의하다가 이 복사 문제에 부딪혔습니다.
Ruby는 백만 가지 방법을 가지고 있기 때문에 Enumerable을 사용하는 또 다른 방법이 있습니다.
h0 = { "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
h1 = h0.inject({}) do |new, (name, value)|
new[name] = value;
new
end
아래를 사용하여 Hash 개체를 딥 복사할 수 있습니다.
deeply_copied_hash = Marshal.load(Marshal.dump(original_hash))
Deep_Copy에 대한 대안적인 방법은 저에게 도움이 되었습니다.
h1 = {:a => 'foo'}
h2 = Hash[h1.to_a]
이것은 h2가 h1의 참조가 아닌 h1의 배열 표현을 사용하여 형성되기 때문에 deep_copy를 생성했습니다.
언급URL : https://stackoverflow.com/questions/4157399/how-do-i-copy-a-hash-in-ruby
'IT' 카테고리의 다른 글
반복하는 동안 값 변경 (0) | 2023.06.02 |
---|---|
배열에 다른 배열의 값이 포함되어 있습니까? (0) | 2023.06.02 |
SQL Server 날짜/시간 LIKE 선택? (0) | 2023.06.02 |
"이전 형제" 선택기가 있습니까? (0) | 2023.06.02 |
배열이 비어 있는지 또는 존재하는지 확인하는 방법은 무엇입니까? (0) | 2023.06.02 |