Domanda

arr = ["red","green","yellow"]

arr2 = arr.clone
arr2[0].replace("blue")

puts arr.inspect
puts arr2.inspect

produce:

["blue", "green", "yellow"]
["blue", "green", "yellow"]

Esiste un modo per fare una copia completa di un array di stringhe, altro che usare il maresciallo mi pare di capire che è un hack.

che potevo fare:

arr2 = []
arr.each do |e|
  arr2 << e.clone
end

, ma non sembra molto elegante, o efficiente.

Grazie

È stato utile?

Soluzione

La seconda soluzione può essere ridotto a arr2 = arr.map do |e| e.dup end (a meno che non hai veramente bisogno il comportamento di clone, si consiglia di utilizzare dup invece).

Oltre a questo i vostri due soluzioni sono fondamentalmente le soluzioni standard per eseguire una copia profonda (anche se la seconda versione è solo un livello profondo (cioè se lo si utilizza su un array di array di stringhe, si può ancora mutare le corde )). Non c'è davvero un modo migliore.

Edit: Ecco un metodo ricorsivo deep_dup che funziona con le matrici arbitrariamente annidati:

class Array
  def deep_dup
    map {|x| x.deep_dup}
  end
end

class Object
  def deep_dup
    dup
  end
end

class Numeric
  # We need this because number.dup throws an exception
  # We also need the same definition for Symbol, TrueClass and FalseClass
  def deep_dup
    self
  end
end

Si potrebbe anche voler definire deep_dup per altri contenitori (come Hash), altrimenti ci si può comunque ottenere una copia per quelli.

Altri suggerimenti

Vi consiglio la vostra idea iniziale, ma scritto un po 'più conciso:

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }

Sono in una situazione simile e molto preoccupati per la velocità. Il modo più veloce per me è stato quello di fare uso di map{&:clone}

Quindi, provate questo:

pry(main)> a = (10000..1000000).to_a.shuffle.map(&:to_s)
pry(main)> Benchmark.ms { b = a.deep_dup }                                                                                     
=> 660.7760030310601
pry(main)> Benchmark.ms { b = a.join("--!--").split("--!--") }
=> 605.0828141160309
pry(main)> Benchmark.ms { b = a.map(&:clone) }
=> 450.8283680770546

È possibile effettuare una copia completa di serie a dal seguente codice:

 Marshal.load(Marshal.dump(a))

Sembra così semplice .. Basta eseguire il codice qui sotto:

a = [1,2,3]
b = [].replace(a)

b[1] = 5

puts a
puts b

Esegui sopra il codice e si noterà la differenza. Cheers!

È possibile utilizzare questo hack:

arr1 = %w{ red green blue }
arr2 = arr1.join("--!--").split("--!--")

Ma è solo per divertimento:)

arr2[0].replace("lol")
p arr1
#=> ["red", "green", "blue"]
p arr2
#=> ["lol", "green", "blue"]

E funziona solo per 1 array di livello

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top