2009-10-22 5 views
0

Grâce à l'aide de a previous question, j'ai le code suivant renvoyant les résultats attendus avec find_all.Modification de la variable set à array find_all semble modifier le tableau original dans Ruby

tableau original (trié par votes [0]):

votes_array = [{"votes"=>[13], "id"=>"4", "elected"=>0}, {"votes"=>[12], "id"=>"1", "elected"=>0}, {"votes"=>[8], "id"=>"3", "elected"=>0}, {"votes"=>[3], "id"=>"2", "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}]

Et le code qui court après ce tableau:

grouped_last = [] 
grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] } 
if grouped_last.length > 1 
    grouped_last.each do |candidate| 
    candidate["votes"][0] += 10 # another value is actually inserted here 
    end 
end 

Le problème est que cela affecte le tableau original - comme je le pense, car find_all est juste un filtre.

Existe-t-il un moyen d'effectuer la même fonction que tout trouver avec map/collect afin qu'il crée un nouveau tableau qui n'affecte pas l'original? Mon cerveau est pétillant essayant de travailler ceci dehors aujourd'hui!

EDIT: Voyons si je peux clarifier cela un peu. J'utilise le tableau votes_array pour stocker un ensemble de valeurs pour chaque étape d'un processus de vote (en utilisant Single Transferrable Vote) par candidat.

Pour chaque tour, le candidat ayant le moins de votes est éliminé et les votes de préférence suivants pour ce candidat sont transférés aux candidats concernés prêts pour le tour suivant.

Cependant, s'il y a plus d'un candidat avec les mêmes voix les plus bas, puis les votes à venir de préférence pour chaque candidat sont comparés et le plus faible nombre de candidats Suffrages signaux du candidat éliminé.

Ce que j'essaie de faire avec cette partie est de trouver le candidat à éliminer.

Je suis désireux de créer un nouveau tableau contenant les candidats les plus bas de vote du tableau original, puis ajoutez une valeur (déterminée par un autre tableau tracé prévu ailleurs). Une fois que j'ai alors grouped_last avec les nouvelles valeurs, je vais trier et analyser à nouveau pour la dernière position.

Le problème est que je veux que le dernier groupe soit un tableau autonome et n'affecte pas le tableau/hachage original.

+0

Je ne suis pas sûr de ce que vous essayez de faire ici en termes de résultat attendu. – tadman

+0

J'espère que la clarification aide un peu plus tadman? – Les

Répondre

2

votre tableau d'origine est un tableau de hachages. find_all renvoie un nouveau tableau, mais le contenu de ce tableau fait référence aux hachages d'origine. essayez ceci:

def deep_copy(obj) 
    Marshal.load(Marshal.dump(obj)) 
end 

grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] } 
grouped_last = deep_copy(grouped_last) 

aussi, grouped_last = [] ne fait rien; vous n'avez pas besoin d'initialiser les variables de cette façon.

Edit: cette session devrait irb le rendre plus clair ce qui se passe:

>> votes_array.map {|x| x.object_id} 
=> [80823078, 80822924, 80822784, 80822644, 80822504] 

>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] } 
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}] 

>> grouped_last.map {|x| x.object_id} 
=> [80822644, 80822504] 

>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }.dup 

=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}] 
>> grouped_last.map {|x| x.object_id} 

=> [80822644, 80822504] 
>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] }.map {|x| x.dup} 

=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}] 
>> grouped_last.map {|x| x.object_id} 
=> [81390302, 81390288] 

>> grouped_last = votes_array.find_all {|i| i["votes"][0] == votes_array.last["votes"][0] } 
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}] 

>> grouped_last = deep_copy(grouped_last) 
=> [{"votes"=>[3], "id"=>22, "elected"=>0}, {"votes"=>[3], "id"=>"0", "elected"=>0}] 

>> grouped_last.map {|x| x.object_id} 
=> [80366188, 80362338] 
+0

Attention, car le tableau pour les votes n'est pas cloné et fait toujours référence à l'original. La méthode dup ne "clone pas en profondeur" comme vous pourriez vous y attendre, mais ne fait qu'une copie de la première couche. – tadman

+0

oups, oui, je pensais que le contenu du tableau était un hachage plat, et dup fonctionnerait bien.n'a pas remarqué que certaines des valeurs étaient elles-mêmes des tableaux. –

+0

Merci Martin - cela fonctionne comme un charme! – Les

Questions connexes