我有两个数组:
var current_items = [{hash: 1}, {hash: 2}, {hash: 3}];
var next_items = [{hash: 3}, {hash: 4}, {hash: 5}];
第一个数组表示当前渲染的项目,另一个表示要渲染的下一个项目(当然简化 - 真实对象包含更多信息)。
我需要通过推/拼接将current_items
数组替换为新项目。问题是,我不能仅使用新项目覆盖current_items
:与next_items
中的项目具有相同哈希值的所有当前项目必须保持原样 (如果对象被更改/覆盖,则会不必要地再次渲染项目。)
我想第一步是删除/拼接current_items
中未包含在next_items中的所有项目:current_items将变为[{hash: 3}]
(保留哈希3,因为它也包含在next_items中)。
然后从next_items
中删除current_items
中已包含的所有项目,next_items
变为[{hash: 4}, {hash: 5}]
最后将剩余的next_items
与current_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}]
有更容易/更清洁/更短的方法吗?
答案 0 :(得分:2)
使用Array.filter()
,Array.concat()
,Array.splice()
,JSON.stringify()
和JSON.parse()
函数的解决方案:
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;
答案 1 :(得分:1)
你可以使用两个哈希表来进行哈希和拼接。稍后将不包含的对象推送到current_items
。
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;
答案 2 :(得分:1)
您可以执行以下操作;
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;
另一种明确的工作方式是:
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;
答案 3 :(得分:1)
您可以执行以下操作,只要您的数组根据哈希进行排序(检查两次,我不确定它是否适用于每个配置)。
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;
虽然我会做一些更简单的事情:
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;