-2
votes

Comment travailler avec tableau sans changer ses valeurs initiales?

Je suis un débutant. Jusqu'à présent, je suis en contact avec deux langues, rubis et python. J'ai également lu quelques essais sur les pointeurs C ++, j'ai eu un peu de confusion avec des objets de tableau et comment manipuler la valeur à l'intérieur. J'ai constaté que, y compris une marque d'exclamation dans la méthode, peut changer la matrice sans mission. Cependant, parfois ça ne le fait pas; J'apprécie que quelqu'un puisse expliquer la nature de la matrice, qu'est-ce qu'ils sont un lieu de stockage de valeurs ou sont-ils la collecte de valeurs? Plus spécifiquement, si je divisez les fonctions de rubis dans deux groupes: Celui qui peut modifier les valeurs de la matrice sans attribution directement, et ceux qui ont besoin d'affectation, pourriez-vous me donner quelques exemples de
Dans l'exemple suivant, je ne comprends pas pourquoi les valeurs de mon tableau initial sont modifiées. de
Voici mon exemple de code:

edges = [[[1, 2], [100, 200]], [[700, 400], [1000, 2000]]]

new_edges = Array.new(edges)
new_edges.map{|edge| edge.map{|point| point.insert(0, 808912)}}

edges
#=> [[[808912, 1, 2], [808912, 100, 200]], [[808912, 700, 400], [808912, 1000, 2000]]]

new_edges
#=> [[[808912, 1, 2], [808912, 100, 200]], [[808912, 700, 400], [808912, 1000, 2000]]]


7 commentaires

On dirait que vous créez NEW_EDGES TRAY deux fois. Une fois avec une array.new et deux fois avec de nouvelles_edges.map. Pourquoi le faites-vous de cette façon? Qu'est-il arrivé quand vous avez randonnée ce code dans le terminal?


Existe-t-il une meilleure façon de le faire? Pourriez-vous me donner quelques suggestions, merci.


Well Array.New (bords) semble bien ... Mais quel est le problème? Vous devez inclure les résultats lorsque vous exécutez ce code, c'est-à-dire. message d'erreur ou sortie.


Duplicaté possible de Comment initialiser un tableau en une étape en utilisant Ruby?


Ce qu'il est initialement: [[[[[1, 2], [100, 200]], [[700, 400], [1000, 2000]]], ce que je veux: [[[808912, 1, 2], [ 808912, 100, 200]], [[808912, 700, 400], [808912, 1000, 2000]]], et je dois utiliser la valeur initiale plus tard


Les premiers puts résultent du terminal sont les suivants: [[[[808912, 100, 200], [808912, 100, 200]] [[808912, 700, 400], [808912, 1000, 2000]]]. Le deuxième résultat est le suivant: [[[[808912, 1, 2], [808912, 100, 200]] [[808912, 700, 400], [808912, 1000, 2000]]]


Laissez-nous Continuez cette discussion dans le chat .


3 Réponses :


1
votes

Vous commencez avec

  def deep_dup
    new_arr = []
    self.each do |ele|
      if ele.is_a? Array
        new_arr << ele.deep_dup
      else
        new_arr << ele
      end
    end
   new_arr
  end


3 commentaires

Ruby n'a pas profond_dup . ActiveSupport fait (et donc rails fait aussi).


Oh, je viens de googler et j'ai mal interprété la documentation. Mon mauvais, je viens de voir #deep_dup, mais ça doit avoir été active et non rubis. En outre, votre solution est bien plus d'espace et de temps efficace, haha. Il suffit d'utiliser une méthode qui ne mute pas le tableau d'origine est beaucoup mieux que Deep_dupping l'original, puis utilisez des méthodes qui mutent.


Une manière un peu pirate de clone profonde un tableau sans utiliser de rails est marshal.load marshal.dump (my_array) . Marshal.Dump Porte le tableau dans un format de chaîne, lequel marshal.load décompresse dans un tableau.



6
votes

Votre code a les mêmes problèmes que cela serait en python: xxx pré>

i.e. Vous transformez la matrice extérieure, mais les matrices internes ne sont maintenues que par référence, et la modification ainsi (par insert code>) modifie la teneur en profondeur des deux bords code> et et new_edges code>. Ces types de problèmes sont très facilement compris en progressant de votre code avec Cet outil (malgré le nom, Cela fonctionne à la fois pour Python et Ruby). P>

en rubis, au lieu d'utiliser insert code>, qui modifie une matrice, vous pouvez utiliser + code>, qui fait Non: P>

edges = [[[1, 2], [100, 200]], [[700, 400], [1000, 2000]]]
new_edges = edges.map { |edge| edge.map { |point| [808912] + point } }
# => [[[808912, 1, 2], [808912, 100, 200]], [[808912, 700, 400], [808912, 1000, 2000]]]
edges
# => [[[1, 2], [100, 200]], [[700, 400], [1000, 2000]]]


1 commentaires

Merci. J'ai aussi trouvé une autre manière: 'new_edges = marshal.load (Marshal.dump (bords))' 'New_edges.map {| Point | point.insert (0, 808912)} '



3
votes

Voici une situation plus générale qui illustre le problème que vous rencontrez et des moyens de la corriger. Supposons que nous ayons les tableaux imbriqués suivants: xxx pré>

A0 code>, a1 code>, a code> et bords code> avoir des identifiants d'objet uniques: p> xxx pré>

pour la lisibilité, j'ai supprimé les sept premiers chiffres de chacun des ID d'objet, qui dans tous les cas est 4833847 . Remarque bords [0] [1] [0] # => 3 code> et 3.Object_id # => 7 code>. Pour des raisons d'efficacité, des entiers (et certains autres objets rubis ont des identifiants d'objet fixes, petits, d'objets. P>

créent maintenant un nouveau tableau à partir de Bords code> à l'aide de la méthode Array :: Nouveau : P>

edges[0][1][0] = 3

edges
  #=> [[[1, 2], [3, 4]]] 
new_edges
  #=> [[[1, 2], [5, 4]]] 


0 commentaires