2013-08-24 3 views
5

Je transmets 2 tableaux à une fonction et je souhaite déplacer une entrée spécifique d'un tableau vers un autre. La fonction moveDatum elle-même utilise les méthodes underscorejs reject et filter. Mon problème est, les tableaux d'origine ne sont pas modifiés, comme si je passais les tableaux comme valeur et non comme référence. L'entrée spécifique est correctement déplacée, mais comme je l'ai dit, l'effet est seulement local. Que dois-je changer pour que les tableaux originaux changent également?changement de tableau transmis à la fonction

Appelez la fonction:

this.moveDatum(sourceArr, targetArr, id) 

Fonction lui-même:

function moveDatum(srcDS, trgDS, id) { 
    var ds = _(srcDS).filter(function(el) { 
     return el.uid === uid; 
    }); 
    srcDS = _(srcDS).reject(function(el) { 
     return el.uid === uid; 
    }); 
    trgDS.push(ds[0]); 
    return this; 
} 

Merci pour l'aide

+1

Vous ne pouvez pas faire cela avec '.filter()' ou '.reject()' car ils créent de nouveaux tableaux. Vous pouvez changer le contenu de 'targetArr' en modifiant' trgDS' avec 'trgDS.push (ds [0])' (comme vous le faites), car les deux font référence au même tableau, mais vous ne pouvez pas provoquer 'sourceArr' pour faire référence à un nouveau tableau en affectant 'srcDS' à un nouveau tableau. – nnnnnn

+0

Peut-être que vous pouvez trouver cette question et les explications utiles: http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value – Stefan

+0

@nnnnnn Merci, je pense que je comprends maintenant ce qui est en cours, je référence fondamentalement srcDS au nouveau tableau créé avec reject() et perd la référence au tableau originellement passé que je veux vraiment changer, y aurait-il un moyen facile de résoudre ce problème? – macg

Répondre

2

Copier sur chaque match avant de le supprimer en utilisant des méthodes qui modifient tableaux, par exemple splice.

function moveDatum(srcDS, trgDS, id) { // you pass an `id`, not `uid`? 
    var i; 
    for (i = 0; i < srcDS.length; ++i) { 
     if (srcDS[i].uid === uid) { 
      trgDS.push(srcDS[i]); 
      srcDS.splice(i, 1); 
      // optionally break here for just the first 
      i--; // remember; decrement `i` because we need to re-check the same 
       // index now that the length has changed 
     } 
    } 
    return this; 
} 
+0

grâce à vous aussi mate =) – macg

+0

@macg si vous pensez que la réponse de Paul a été utile, pensez à upvote s'il vous plaît. – Stefan

+0

@Stefan Je l'ai considéré, mais stackoverflow n'est pas très prévenant avec moi ayant seulement 13 réputation =) J'ai besoin de deux autres pour upvote – macg

3

Comme mentionné dans les commentaires, vous affectez srcDS pour référencer un nouveau tableau retourné par .reject(), perdant ainsi la référence au tableau transmis à l'origine depuis l'extérieur de la fonction.

Vous devez effectuer directement vos opérations de tableau sur le tableau original, peut-être quelque chose comme ceci:

function moveDatum(srcDS, trgDS, id) { 
    var ds; 
    for (var i = srcDS.length - 1; i >= 0; i--) { 
     if (srcDS[i].uid === id) { 
      ds = srcDS[i]; 
      srcDS.splice(i,1); 
     } 
    } 
    trgDS.push(ds); 
    return this; 
} 

J'ai mis en place la boucle pour revenir en arrière afin que vous n'avez pas à vous soucier de la index de boucle i désynchronisation lorsque .splice() supprime des éléments de la matrice. La boucle arrière signifie également ds finit par référencer le premier élément de srcDS qui correspond, ce que je suppose que vous avez l'intention puisque votre code original avait trgDS.push(ds[0]).

Si vous savez que le tableau ne contiendra jamais qu'un seul match alors bien sûr, peu importe si vous allez en avant ou en arrière, et vous pouvez ajouter un break à l'intérieur du if puisqu'il ne sert à rien de continuer la boucle une fois que vous avez un match.

(Aussi je pense que vous avez eu une faute de frappe, vous testiez === uid au lieu de === id.)

+0

merci, fonctionne comme un charme – macg

Questions connexes