2013-08-24 14 views
5

Ho passato 2 array a una funzione e voglio spostare una voce specifica da una matrice all'altra. La funzione moveDatum utilizza i metodi underscorejs per rifiutare e filtrare. Il mio problema è che gli array originali non vengono modificati, come se stessi passando gli array come valore e non come riferimento. La voce specifica viene spostata correttamente, ma come ho detto, l'effetto è solo locale. Che cosa devo cambiare, anche gli array originali cambiano?cambia array passato alla funzione

Chiamare la funzione:

this.moveDatum(sourceArr, targetArr, id) 

funzione stessa:

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; 
} 

Grazie per l'aiuto

+1

Non è possibile farlo con '.filter()' o '.reject()' perché creano nuovi array. Puoi cambiare il contenuto di 'targetArr' modificando' trgDS' con 'trgDS.push (ds [0])' (come stai facendo), perché entrambi si riferiscono allo stesso array, ma non puoi causare 'sourceArr' fare riferimento a un nuovo array assegnando 'srcDS' a un nuovo array. – nnnnnn

+0

Forse è possibile trovare questa domanda e spiegazioni utili: http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value – Stefan

+0

@nnnnnn Grazie, credo di aver capito ora che cosa è succedendo, in pratica faccio riferimento a srcDS al nuovo array creato con reject() e perdo il riferimento alla matrice originariamente passata che in realtà voglio cambiare, ci sarebbe un modo semplice per risolvere questo problema? – macg

risposta

2

copia su ogni partita prima di eliminarlo utilizzando metodi che modificano Array, per esempio 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

grazie anche a te amico =) – macg

+0

@macg se pensi che la risposta di Paolo sia stata utile, considera di revocarla per favore. – Stefan

+0

@Stefan L'ho preso in considerazione, ma lo stackoverflow non è molto premuroso con il fatto che ho solo 13 reputazione =) Ho bisogno di altri due per l'upvote – macg

3

Come accennato nei commenti, si sta assegnando srcDS fare riferimento a una nuova matrice restituita per .reject(), e quindi perdere il riferimento alla matrice originariamente inoltrata dall'esterno della funzione.

È necessario eseguire le operazioni di matrice direttamente sulla matrice originale, forse qualcosa di simile:

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; 
} 

Ho installato il ciclo per tornare indietro in modo che non devi preoccuparti per il l'indice di loop i non sincronizzato quando .splice() rimuove gli elementi dall'array. Il ciclo all'indietro significa anche ds che fa riferimento al primo elemento in srcDS corrispondente, che è ciò che presumo che si intenda dal momento che il codice originale era trgDS.push(ds[0]).

Se vi capita di sapere che l'array sarà sempre e solo contenere esattamente un partita poi, naturalmente, non importa se si va avanti o indietro, ed è possibile aggiungere un break all'interno della if poiché non c'è motivo di continuare il ciclo una volta che hai una partita.

(Anche io penso tu avessi un errore di battitura, si stava testando === uid invece di === id.)

+0

grazie, funziona come un incantesimo – macg

Problemi correlati