Javascript AngularJS:按ID合并对象,即在ID相同时替换旧条目
我在AngularJS中使用Ionic,通过$http使用LocalFower数据库和AJAX。我的应用程序有一个包含以下数据的新闻流:Javascript AngularJS:按ID合并对象,即在ID相同时替换旧条目,javascript,angularjs,ionic,Javascript,Angularjs,Ionic,我在AngularJS中使用Ionic,通过$http使用LocalFower数据库和AJAX。我的应用程序有一个包含以下数据的新闻流: { "feed":[ { "id":"3", "title":"Ein Hund", "comments:"1" }, { "id":"2", "title"
{
"feed":[
{
"id":"3",
"title":"Ein Hund",
"comments:"1"
},
{
"id":"2",
"title":"Eine Katze",
"comments":"2"
}
],
"ts":"20150907171943"
}
{
"feed":[
{
"id":"2",
"title":"Eine Katze",
"comments":"4"
}
],
"ts":"20150907171944"
}
ts
代表时间戳。我的应用程序通过LocalFower在本地保存提要
应用程序启动时,首先加载本地保存的项目:
$localForage.getItem("feed").then(function(val) { vm.feed = val; })
然后,它加载新的或更新的项目(ts
),并合并新旧数据:
angular.extend(vm.feed, response.data.feed);
更新的项目如下所示:
{
"feed":[
{
"id":"3",
"title":"Ein Hund",
"comments:"1"
},
{
"id":"2",
"title":"Eine Katze",
"comments":"2"
}
],
"ts":"20150907171943"
}
{
"feed":[
{
"id":"2",
"title":"Eine Katze",
"comments":"4"
}
],
"ts":"20150907171944"
}
也就是说,提要项2的注释计数已从2更改为4。当我合并新旧数据时,vm.feed
有两个id=2的项
angularjs是否具有内置的“按id合并”功能,即。E从源复制到目标(如果是新元素),还是替换旧元素?如果angularjs没有这样的功能,那么实现它的最佳方法是什么
提前谢谢 角度合并(vm.feed,response.data.feed)代码>
//编辑
它可能无法正确合并,因此您必须手动更新所有属性。更新
ts
属性,然后找到id为id的对象并将其替换。没有内置项,我通常编写自己的合并函数:
(function(){
function itemsToArray(items) {
var result = [];
if (items) {
// items can be a Map, so don't use angular.forEach here
items.forEach(function(item) {
result.push(item);
});
}
return result;
}
function idOf(obj) {
return obj.id;
}
function defaultMerge(newItem, oldItem) {
return angular.merge(oldItem, newItem);
}
function mergeById(oldItems, newItems, idSelector, mergeItem) {
if (mergeItem === undefined) mergeItem = defaultMerge;
if (idSelector === undefined) idSelector = idOf;
// Map retains insertion order
var mapping = new Map();
angular.forEach(oldItems, function(oldItem) {
var key = idSelector(oldItem);
mapping.set(key, oldItem);
});
angular.forEach(newItems, function(newItem) {
var key = idSelector(newItem);
if (mapping.has(key)) {
var oldItem = mapping.get(key);
mapping.set(key, mergeItem(newItem, oldItem));
} else {
// new items are simply added, will be at
// the end of the result list, in order
mapping.set(key, newItem);
}
});
return itemsToArray(mapping);
}
var olds = [
{ id: 1, name: 'old1' },
{ id: 2, name: 'old2' }
];
var news = [
{ id: 3, name: 'new3' },
{ id: 2, name: 'new2' }
];
var merged = mergeById(olds, news);
console.log(merged);
/* Prints
[
{ id: 1, name: 'old1' },
{ id: 2, name: 'new2' },
{ id: 3, name: 'new3' }
];
*/
})();
这将根据id从旧项构建映射
,合并到新项中,并将映射转换回列表。幸运的是,根据规范,Map
对象将按插入顺序对条目进行迭代。您可以提供您的idSelector
和mergeItem
功能。谢谢hege_hegedus。根据您的代码,我编写了自己的代码,并尝试使用较少的循环来加快速度:
function updateCollection(localCollection, fetchedCollection) {
angular.forEach(fetchedCollection, function(item) {
var append = true;
for (var i = 0; i < localCollection.length; i++) {
if (localCollection[i].id == item.id) {
// Replace item
localCollection[i] = item;
append = false;
break;
} else if (localCollection[i].id > item.id) {
// Add new element at the right position, if IDs are descending check for "< item.id" instead
localCollection.splice(i, 0, item);
append = false;
break;
}
}
if (append) {
// Add new element with a higher ID at the end
localCollection.push(item);
// When IDs are descending use .unshift(item) instead
}
});
}
函数updateCollection(localCollection,fetchedCollection){
angular.forEach(fetchedCollection,函数(项){
var=true;
for(var i=0;iitem.id){
//在正确的位置添加新元素,如果id是递减的,则改为检查“
我认为,仍有改进的余地。E通过所有对象的迭代应该使用二进制搜索,因为所有项目都是按id排序的。merge意味着您需要维护原始项目的某些属性,但从您的描述来看,我不确定是否是这样。用新项目完全替换旧项目更容易,但这将是手动的。对于返回的每个项,确定它是否已在集合中。如果是,请更换。如果否,则将其添加到末尾。