查找和替换数组中的对象(基于 id)

Posted

技术标签:

【中文标题】查找和替换数组中的对象(基于 id)【英文标题】:Find and replace object in array (based on id) 【发布时间】:2019-07-19 10:47:07 【问题描述】:

这里有点谜...我想遍历allItems 并返回allItems,但替换为任何匹配其id 的newItems。如何在 id 上查找匹配项,然后将其替换为数组中的正确对象?

const allItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'old',
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'old'
  
]

const newItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  
]

到目前为止我尝试了什么:

for(let i = 0; i < allItems.length; i++) 
  if(newItems.indexOf(allItems[i].id) > -1)
    allItems[i] = newItems
  

如何获取newItems中对象的位置,然后将其替换为allItems

【问题讨论】:

【参考方案1】:

使用Array.mapArray.find()

const allItems = [
   'id': 1, 'category_id': 1, 'text': 'old' ,
   'id': 2, 'category_id': 1, 'text': 'old' 
];

const newItems = [
   'id': 1, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' ,
   'id': 2, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' 
];

const result = allItems.map(x => 
  const item = newItems.find(( id ) => id === x.id);
  return item ? item : x;
);

console.log(result);

当对find 的调用返回undefined 时,甚至可以通过使用逻辑或返回原始项目来缩短这一点:

const result = allItems.map(x => newItems.find(( id ) => id === x.id) || x);

关于您的代码,您不能使用indexOf,因为它只比较数组和对象的原始值或引用。

【讨论】:

【参考方案2】:

只需像这样使用map

const allItems = [
    'id': 1,
    'category_id': 1,
    'text': 'old',
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'old'
  
];
const newItems = [
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  
];

const replacedItems = allItems.map(e => 
  if (newItems.some(( id ) => id == e.id)) 
    return newItems.find(( id ) => id == e.id);
  
  return e;
);

console.log(replacedItems);

【讨论】:

【参考方案3】:

只需使用一个简单的 Array.map 和一个方法来检查另一个数组。

const allItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'old',
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'old'
  ,
  
    'id': 3,
    'category_id': 1,
    'text': 'old_same'
  
  
]

const newItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  
]

const findNewItem = (oldItem) => newItems.find(item => item.id === oldItem.id);

let arr = allItems.map(item => findNewItem(item)||item);

console.log(arr);

【讨论】:

【参考方案4】:

根据输入数组的大小,您可以考虑添加一个中间步骤来构建您的newItems 的“映射”,其中该映射的键是项目的id

使用这样的映射可以更快地协调(和替换)allItems 数组中的项目与 newItems 数组中的项目:

function replaceItemsOnId(items, replacement) 

  /* 
  Create a map where the key is the id of replacement items.
  This map will speed up the reconciling process in the 
  subsequent "map" stage
  */
  const replacementMap = replacement.reduce((map, item) => 

    map[ item.id ] = item
    return map;

  , )

  /*
  Map the items to a new array where items in the result array
  are either clones of the orignals, or replaced by items of 
  "replacement" array where thier id matches the item being mapped 
  */
  return items.map(item => 

    const use = replacementMap[ item.id ] || item

    return  ...use 

  )


const allItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'old',
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'old'
  
]

const newItems = [
  
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  ,
  
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  
]


console.log(replaceItemsOnId(allItems, newItems))

【讨论】:

【参考方案5】:

您可以通过 id 获得对您要查找的对象的引用,但这还不够,因为您需要索引才能在 allItem (allItem[index] = newItem) 中替换它,所以我建议先找到该索引,如下所示:

for (let item of newItems) 
    let indexNewItem = allItems.map(function (e)  return e.id ).indexOf(item.id);
    allItems[indexNewItem] = item

这应该可以工作

【讨论】:

以上是关于查找和替换数组中的对象(基于 id)的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB $查找具有不同值的对象数组

查找重复项并将其替换为具有相同索引位置的新数组

用 inArray 查找数组中的对象

javascript 根据键值在数组中查找和删除对象

查找和替换数组中的重复项

查找和替换元胞数组中的值