Admito que sou um pouco novato em rubi (agora estou escrevendo scripts de rake). Na maioria dos idiomas, os construtores de cópias são fáceis de encontrar. Meia hora de busca não encontrou em rubi. Quero criar uma cópia do hash para poder modificá-lo sem afetar a instância original.
Alguns métodos esperados que não funcionam conforme o esperado:
h0 = { "John"=>"Adams","Thomas"=>"Jefferson","Johny"=>"Appleseed"}
h1=Hash.new(h0)
h2=h1.to_hash
Enquanto isso, eu recorri a essa solução deselegante
def copyhash(inputhash)
h = Hash.new
inputhash.each do |pair|
h.store(pair[0], pair[1])
end
return h
end
Hash
objetos simples , a resposta fornecida é boa. Se você estiver lidando com objetos do tipo Hash provenientes de lugares que você não controla, considere se deseja que a classe singleton associada ao Hash seja duplicada ou não. Consulte stackoverflow.com/questions/10183370/…Respostas:
O
clone
método é o padrão de Ruby, maneira integrada de fazer uma cópia superficial :Observe que o comportamento pode ser substituído:
fonte
Marshal.load(Marshal.dump(h))
.Como outros já apontaram,
clone
farão isso. Esteja ciente de queclone
um hash faz uma cópia superficial. Ou seja:O que está acontecendo é que as referências do hash estão sendo copiadas, mas não os objetos aos quais as referências se referem.
Se você deseja uma cópia profunda, então:
deep_copy
funciona para qualquer objeto que possa ser empacotado. A maioria dos tipos de dados internos (matriz, hash, cadeia etc.) pode ser empacotada.Marshalling é o nome de Ruby para serialização . Com o empacotamento, o objeto - com os objetos a que se refere - é convertido em uma série de bytes; esses bytes são usados para criar outro objeto como o original.
fonte
Marshal.load(Marshal.dump(o))
a cópia profunda? Eu realmente não consigo entender o que acontece nos bastidoresh1[:a] << 'bar'
modificar o objeto original (a string apontada por h1 [: a]), mas se o fizerh1[:a] = "#{h1[:a]}bar"
, criaria um novo objeto de string e apontariah1[:a]
para ele, enquantoh2[:a]
está ainda apontando para a string antiga (não modificada).Se você estiver usando o Rails, poderá:
http://apidock.com/rails/Hash/deep_dup
fonte
O hash pode criar um novo hash a partir de um hash existente:
fonte
Também sou novato no Ruby e enfrentei problemas semelhantes ao duplicar um hash. Use o seguinte. Não faço ideia da velocidade desse método.
fonte
Conforme mencionado na seção Considerações de segurança da documentação do Marshal ,
Aqui está um exemplo de como fazer clonagem usando JSON no Ruby:
fonte
Use
Object#clone
:(Confusamente, a documentação para
clone
diz queinitialize_copy
é a maneira de substituir isso, mas o link para esse método noHash
direciona você areplace
substituir ...)fonte
Como o método de clonagem padrão preserva o estado congelado, não é adequado para criar novos objetos imutáveis com base no objeto original, se você desejar que os novos objetos sejam ligeiramente diferentes do original (se você gosta de programação sem estado).
fonte
O clone é lento. Pois o desempenho provavelmente deve começar com o hash e a mesclagem em branco. Não abrange casos de hashes aninhados ...
fonte
Este é um caso especial, mas se você estiver começando com um hash predefinido que deseja pegar e fazer uma cópia, poderá criar um método que retorne um hash:
O cenário particular que eu tive foi que eu tinha uma coleção de hashes de esquema JSON onde alguns hashes foram construídos a partir de outros. Inicialmente, eu as defini como variáveis de classe e me deparei com esse problema de cópia.
fonte
você pode usar abaixo para copiar objetos Hash em profundidade.
fonte
Como o Ruby tem um milhão de maneiras de fazer isso, aqui está outra maneira de usar o Enumerable:
fonte
Maneira alternativa ao Deep_Copy que funcionou para mim.
Isso produziu uma cópia_ profunda, já que h2 é formado usando uma representação de matriz de h1 em vez das referências de h1.
fonte