Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

change array passed to function

I pass 2 arrays to a function and want to move a specific entry from one array to another. The moveDatum function itself uses underscorejs' methods reject and filter. My Problem is, the original arrays are not changed, as if I was passing the arrays as value and not as reference. The specific entry is correctly moved, but as I said, the effect is only local. What do I have to change, to have the original arrays change as well?

Call the function:

this.moveDatum(sourceArr, targetArr, id)

Function itself:

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

Thanks for the help

like image 847
David M Avatar asked Aug 24 '13 13:08

David M


2 Answers

Copy over every match before deleting it using methods which modify Arrays, e.g. 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;
}
like image 31
Paul S. Avatar answered Sep 20 '22 19:09

Paul S.


As mentioned in the comments, you're assigning srcDS to reference a new array returned by .reject(), and thus losing the reference to the array originally passed in from outside the function.

You need to perform your array operations directly on the original array, perhaps something like this:

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

I've set up the loop to go backwards so that you don't have to worry about the loop index i getting out of sync when .splice() removes items from the array. The backwards loop also means ds ends up referencing the first element in srcDS that matches, which is what I assume you intend since your original code had trgDS.push(ds[0]).

If you happen to know that the array will only ever contain exactly one match then of course it doesn't matter if you go forwards or backwards, and you can add a break inside the if since there's no point continuing the loop once you have a match.

(Also I think you had a typo, you were testing === uid instead of === id.)

like image 60
nnnnnn Avatar answered Sep 18 '22 19:09

nnnnnn