arrays - zusammensetzen - perl variablen typen




Warum hängt ein Wert an ein Array in hash auch die andere Variable an, der es zugewiesen wurde? (4)

Alle Objekte in Ruby werden durch Referenz zugewiesen, mit Ausnahme von True, False, Nil und Fixnums, die speziell behandelt werden.

Sie können es ausprobieren, indem Sie auf object_id schauen

irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> b = a
=> [1, 2, 3]
irb(main):003:0> a.object_id == b.object_id
=> true

Um eine Kopie eines Objekts zu erstellen, verwenden Sie .dup .

irb(main):005:0> b = a.dup
=> [1, 2, 3]
irb(main):006:0> a.object_id == b.object_id
=> false

Für Ihr Beispiel benötigen Sie eine tiefe Kopie, so dass Sie es tun können

Marshal.load(Marshal.dump(hash))

Damit,

irb(main):037:0> a = {a: []}
=> {:a=>[]}
irb(main):038:0> b = Marshal.load(Marshal.dump(a))
=> {:a=>[]}
irb(main):039:0> b[:a] << 1
=> [1]
irb(main):040:0> b
=> {:a=>[1]}
irb(main):041:0> a
=> {:a=>[]}

Beispielcode:

hash_of_array = { a: [] }
b = hash_of_array
c = hash_of_array

b[:a] << 1

puts b # => { a: [1] }
puts c # => { a: [1] }

Warum haben beide Variablen 1 in ihrem Array? Ich habe es nur an die Variable b angehängt.

Anprobiert

  • Ruby Version 2.3.1, 2.4.0
  • Rbenv

Ich kenne eine Person namens John. Manche nennen ihn Johny. Johny wurde heute erschossen. Warum wurde John auch erschossen?

foo = _something_

_something_ einfach den alternativen Namen foo zu _something_ . Es klont es nicht und macht keine anderen Spielereien.


Wie bereits erwähnt, ausgezeichnete Antworten, das Problem, das Sie gegenüberstellen, ist, dass a und b das gleiche Objekt sind. Eine andere Antwort (später gelöscht) empfahl die Verwendung der Dup-Methode, wenn eine flache Kopie ausreichend war. Problem ist, dass in Ihren Szenarien eine flache Kopie NICHT gut genug ist.

Ich schlage vor, das full_dup Juwel zu versuchen. Dieser Edelstein fügt eine neue Methode namens full_dup hinzu. Ein full_dup macht eine tiefe Kopie Ihrer Objekte. Also geben Sie Ihr Beispiel:

require 'full_dup'

hash_of_array = { a: [] }
b = hash_of_array.full_dup
c = hash_of_array.full_dup

b[:a] << 1

puts b # => { a: [1] }
puts c # => { a: [] }

Abgesehen davon ist full_dup kein Geschwindigkeitsdämon. Sie sollten reguläres dup benutzen, wenn diese Methode alles ist, was Sie brauchen.

Hoppla; Vergaß zu erwähnen. Ich bin der Autor des full_dup Gems.


In Ihrem Beispiel, und wie von @AndreyDeineko erwähnt , sind b und c grundsätzlich das gleiche Objekt.

Es ist jedoch nicht notwendig, das Verhalten zu zeigen, über das Sie verwirrt sind.

Wichtig ist, dass sie einen Verweis auf das gleiche Array enthalten:

array = []

b = { b: array }
c = { c: array }

puts b == c
#=> false

puts b.object_id == c.object_id
#=> false

puts b[:b].object_id == c[:c].object_id
#=> true

b[:b] << 'test'

p b
# {:b=>["test"]}
p c
# {:c=>["test"]}




hash