通过splice& amp;将数组替换为另一个数组。推动而不触及非唯一值

时间:2016-12-24 20:21:19

标签: javascript arrays push splice

我有两个数组:

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

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

第一个数组表示当前渲染的项目,另一个表示要渲染的下一个项目(当然简化 - 真实对象包含更多信息)。

我需要通过推/拼接将current_items数组替换为新项目。问题是,我不能仅使用新项目覆盖current_itemsnext_items中的项目具有相同哈希值的所有当前项目必须保持原样 (如果对象被更改/覆盖,则会不必要地再次渲染项目。)

我想第一步是删除/拼接current_items中未包含在next_items中的所有项目:current_items将变为[{hash: 3}](保留哈希3,因为它也包含在next_items中)。

然后从next_items中删除current_items中已包含的所有项目,next_items变为[{hash: 4}, {hash: 5}]

最后将剩余的next_itemscurrent_items

联合起来
current_items.push.apply(current_items, next_items); 

会产生[{hash: 3}, {hash: 4}, {hash: 5}]

我目前的解决方案如下:

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

有更容易/更清洁/更短的方法吗?

4 个答案:

答案 0 :(得分:2)

使用Array.filter()Array.concat()Array.splice()JSON.stringify()JSON.parse()函数的解决方案:

&#13;
&#13;
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);
&#13;
&#13;
&#13;

答案 1 :(得分:1)

你可以使用两个哈希表来进行哈希和拼接。稍后将不包含的对象推送到current_items

&#13;
&#13;
var current_items = [{ hash: 1 }, { hash: 2 }, { hash: 3, keep: true /* flag for identify this object */ }],
    next_items = [{ hash: 3 }, { hash: 4 }, { hash: 5 }],
    hashNext = Object.create(null),
    hashCurrent = Object.create(null);

next_items.forEach(function (a) {
    hashNext[a.hash] = true;
});

current_items.reduceRight(function (_, a, i, aa) {
    hashCurrent[a.hash] = true;
    if (!hashNext[a.hash]) {
        aa.splice(i, 1);
    }
}, 0);

next_items.forEach(function (a) {
    if (!hashCurrent[a.hash]) {
        current_items.push(a);
    }
});

console.log(current_items);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 2 :(得分:1)

您可以执行以下操作;

&#13;
&#13;
var current_items = [{hash: 1}, {hash: 2}, {hash: 3}, {hash: 4}],
       next_items = [{hash: 3}, {hash: 4}, {hash: 5}, {hash: 6}],
           result = current_items.filter(h => next_items.some(g => g.hash === h.hash))
                                 .reduce((p,c,i,a) => i ? p.concat(next_items.filter(n => p.every(e => e.hash !== n.hash)))
                                                        : p.concat(a, next_items.filter(n => a.every(e => e.hash !== n.hash))),[]);
console.log(result);
&#13;
&#13;
&#13;

另一种明确的工作方式是:

&#13;
&#13;
var current_items = [{hash: 1}, {hash: 2}, {hash: 3}, {hash: 4}],
       next_items = [{hash: 3}, {hash: 4}, {hash: 5}, {hash: 6}],
            union = current_items.filter(c => next_items.some(n => c.hash === n.hash)),
       separation = next_items.filter(n => !union.some(u => n.hash === u.hash));
           result = union.concat(separation);
console.log(result);
&#13;
&#13;
&#13;

答案 3 :(得分:1)

您可以执行以下操作,只要您的数组根据哈希进行排序(检查两次,我不确定它是否适用于每个配置)。

&#13;
&#13;
var curr = [{hash:1},{hash:2},{hash:3}];
var next = [{hash:3},{hash:4},{hash:5}];

var i = 0;
while (next.length > 0 || i < curr.length) {
  if (next.length == 0) {
    curr.pop();
  } else if (curr.length == i) {
    curr.push(next.shift()), i++;
  } else if (curr[i].hash > next[0].hash) {
    curr.splice(i++, 0, next.shift());
  } else if (curr[i].hash < next[0].hash) {
    curr.splice(i, 1);
  } else {
    next.shift(), i++;
  }
}

console.log("[", curr.map(x => x.hash).join(" "), "]");
console.log("[", next.map(x => x.hash).join(" "), "]");
&#13;
&#13;
&#13;

虽然我会做一些更简单的事情:

&#13;
&#13;
var curr = [{hash:1},{hash:2},{hash:3}];
var next = [{hash:3},{hash:4},{hash:5}];

function cookUpdate (curr, next) {
  var i = 0, j = 0, midd = [];
  while (j < next.length) {
    if (i == curr.length) {
      midd.push(next[j]), j++;
    } else if (curr[i].hash == next[j].hash) {
      midd.push(curr[i]), i++, j++;
    } else if (curr[i].hash > next[0].hash) {
      midd.push(next[j]), j++;
    } else {
      i++;
    }
  }
  return midd;
}

curr = cookUpdate(curr, next);
next = [];

console.log("[", curr.map(x => x.hash).join(" "), "]");
console.log("[", next.map(x => x.hash).join(" "), "]");
&#13;
&#13;
&#13;