Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace array with another array by splice & push without touching non-unique values

I have two arrays:

var current_items = [{hash: 1}, {hash: 2}, {hash: 3}];

var next_items    = [{hash: 3}, {hash: 4}, {hash: 5}];

The first array represents currently rendered items, the other represents the next items to render (simplified of course - the real objects contain a lot more information).

I need to replace the current_items array with the new items just by pushing/splicing. The problem is that I can not just override the current_items with the new items: All current items that have the same hash as an item in next_items must be kept as they are (if the object is changed/overridden the item would be rendered again unnecessarily).

I guess the first step would be to remove/splice all items in current_items that are not contained in next_items: current_items would become [{hash: 3}] (keep hash 3 because it is also contained in next_items).

Then remove all items from next_items that are already contained in current_items, so next_items becomes [{hash: 4}, {hash: 5}]

and finally concat the remaining next_items with the current_items

current_items.push.apply(current_items, next_items); 

which results in [{hash: 3}, {hash: 4}, {hash: 5}]

My current solution looks something like this:

var current_items = [{hash: 1}, {hash: 2}, {hash: 3}];
var next_items    = [{hash: 3}, {hash: 4}, {hash: 5}];

// splice old items
var i = current_items.length, j, found;
while (i--) {
    found = false;
    for (j = 0; j < next_items.length; j++) {
        if (current_items[i]['hash'] === next_items[j]['hash']) {
            found = true;
            break;
        }
    }
    !found && current_items.splice(i, 1);
}

// get unique new items
var unique_new_items = [];
for (i = 0; i < next_items.length; i++) {
    found = false;
    for (j = 0; j < current_items.length; j++) {
        if (next_items[i]['hash'] === current_items[j]['hash']) {
            found = true;
            break;
        }
    }
    !found && unique_new_items.push(next_items[i]);
}

current_items.push.apply(current_items, unique_new_items); 
// [{hash: 3}, {hash: 4}, {hash: 5}]

Is there an easier/cleaner/shorter way to do that?

like image 296
Đinh Carabus Avatar asked Aug 26 '26 01:08

Đinh Carabus


1 Answers

The solution using Array.filter(), Array.concat(), Array.splice(),JSON.stringify() and JSON.parse() functions:

var current_items = [{hash: 1}, {hash: 2}, {hash: 3}],
    next_items    = [{hash: 3}, {hash: 4}, {hash: 5}],
    next_items_stringified = next_items.map(JSON.stringify);

current_items = current_items.filter(function (o) {
  var pos = this.indexOf(JSON.stringify(o));
  return pos !== -1 && this.splice(pos, 1);
}, next_items_stringified).concat(next_items_stringified.map(JSON.parse));

console.log(current_items);
like image 96
RomanPerekhrest Avatar answered Aug 27 '26 15:08

RomanPerekhrest



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!