如何在对象数组中查找和更新值?

Posted

技术标签:

【中文标题】如何在对象数组中查找和更新值?【英文标题】:How can I find and update values in an array of objects? 【发布时间】:2016-05-14 08:47:25 【问题描述】:

我有一个对象数组。我想通过某个字段找到,然后更改它:

var item = ...
var items = [id:2, id:2, id:2];

var foundItem = items.find(x => x.id == item.id);
foundItem = item;

我希望它改变原始对象。如何? (我不在乎它是否也会出现在 Lodash 中。)

【问题讨论】:

让你的新对象item 包含id 键?或者您介意在数组条目中包含来自 item 对象的 id 以及所有属性? 【参考方案1】:

您可以使用findIndex在对象的数组中查找索引并根据需要进行替换:

var item = ...
var items = [id:2, id:2, id:2];

var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;

这假定了唯一的 ID。如果您的 ID 重复(如您的示例中所示),则使用 forEach 可能会更好:

items.forEach((element, index) => 
    if(element.id === item.id) 
        items[index] = item;
    
);

【讨论】:

@georg 不过这会返回一个新数组。 => 函数在 IE11 中不起作用。最近被这个咬了。 使用let 关键字而不是var 可能会更好 仅供参考,这在某些版本的 phantomJS 中不起作用 我更喜欢@CodingIntrigue 使用的更详细的方法,而不是@georg 使用的单行map。弄清楚发生了什么所需的心理体操更少。值得额外的代码行。【参考方案2】:

我最好的方法是:

var item = ...
var items = [id:2, id:2, id:2];

items[items.findIndex(el => el.id === item.id)] = item;

参考findIndex

如果你不想用新对象替换,而是复制item的字段,你可以使用Object.assign

Object.assign(items[items.findIndex(el => el.id === item.id)], item)

作为.map()的替代方案:

Object.assign(items, items.map(el => el.id === item.id? item : el))

Functional approach:

不要修改数组,使用一个新的,这样就不会产生副作用

const updatedItems = items.map(el => el.id === item.id ? item : el)

注意

如果使用得当,对对象的引用不会丢失,因此您甚至可以使用原始对象引用,而不是创建新的引用。

const myArr = [ id: 1 ,  id: 2 ,  id: 9 ];
const [a, b, c] = myArr;
// modify original reference will change object in the array
a.color = 'green';
console.log(myArr[0].color); // outputs 'green'

这个问题通常发生在使用数据库中的列表,然后映射列表以生成 html 内容,该内容将修改列表的元素,然后我们需要更新列表并将其作为列表发送回数据库。

好消息是,保留了引用,因此您可以组织代码以利用它,并将list 视为具有免费标识的对象,这些标识是从 0 到 length -1 的整数。因此,每次访问对象的任何属性时,都以list[i] 进行操作,并且不会丢失引用,并且原始对象会更改。请记住,当您的事实来源只有一个(创建的对象)并且您的应用程序始终始终使用相同的对象(而不是从数据库中获取多次并将其分配给list)时,这很有用组件)。

坏消息是架构是错误的,如果这是你需要的,你应该通过 ids(字典)接收一个对象,比如

 
  1232:  id: 1232, ...,
  asdf234asf:  id: 'asdf234asf', ...,
  ...

这样,您就不会在数组中搜索,这会消耗资源。您“只需在对象中通过键访问”,这是即时且高效的。

【讨论】:

如果原始问题是英文的,请链接到英文页面。此外,此示例假定始终找到对象。 您可以随时将其包装在 try catch 表达式中...对吗? 对于帖子的问题完全是字面意思,他想编辑数组中的一个元素。他不想知道它是否存在,所以我们假设他之前已经这样做了。 @SoldeplataSaketos 是的,您可以将其包装在 try/catch 中,但您不应该这样做,因为找不到该元素并不是例外情况;这是一个标准情况,您应该检查findIndex 的返回值,然后仅在找到元素时更新数组。【参考方案3】:

另一种方法是使用splice。

splice() 方法通过删除或替换现有元素和/或添加新元素 in place 来更改数组的内容。

注意:如果您正在使用响应式框架,它将更新“视图”,您的数组“知道”您已更新它。

答案:

var item = ...
var items = [id:2, id:2, id:2];

let foundIndex = items.findIndex(element => element.id === item.id)
items.splice(foundIndex, 1, item)

如果你只想改变一个项目的值,你可以使用find函数:

// Retrieve item and assign ref to updatedItem
let updatedItem = items.find((element) =>  return element.id === item.id )

// Modify object property
updatedItem.aProp = ds.aProp

【讨论】:

【参考方案4】:

可以使用Filter。

const list = [id:0, id:1, id:2];
let listCopy = [...list];
let filteredDataSource = listCopy.filter((item) => 
       if (item.id === 1) 
           item.id = 12345;
        

        return item;
    );
console.log(filteredDataSource);

数组[对象id:0,对象id:12345,对象id:2]

【讨论】:

我喜欢过滤器,因为它允许创建一个新数组,因此不存在的条目也被“删除”【参考方案5】:

给定一个改变的对象和一个数组:

const item = ...
let items = [id:2, id:3, id:4];

通过迭代数组来用新对象更新数组:

items = items.map(x => (x.id === item.id) ? item : x)

【讨论】:

我认为这是最好的解决方案,因为它具有最好的性能,因为它只遍历数组一次并且还更改了数组的引用,因此它可以避免可变情况 @Spencer 因此映射循环遍历items 数组中的每个项目,并检查该项目的id 是否与const 变量中项目的id 相同。如果找到一个,则将 x 映射到 item,这是 const 变量中的那个,否则它在 items 数组中保留相同的元素 x【参考方案6】:

虽然大多数现有答案都很棒,但我想包括一个使用传统 for 循环的答案,在这里也应该考虑。 OP 请求一个与 ES5/ES6 兼容的答案,并且适用传统的 for 循环:)

在这种情况下使用数组函数的问题在于它们不会改变对象,但在这种情况下,改变是必需的。使用传统 for 循环的性能提升只是一个(巨大的)奖励。

const findThis = 2;
const items = [id:1, ..., id:2, ..., id:3, ...];

for (let i = 0, l = items.length; i < l; ++i) 
  if (items[i].id === findThis) 
    items[i].iAmChanged = true;
    break;
  

虽然我非常喜欢数组函数,但不要让它们成为您工具箱中的唯一工具。如果目的是改变数组,那么它们不是最合适的。

【讨论】:

【参考方案7】:

为我工作

let returnPayments = [ ...this.payments ];

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;

【讨论】:

请不要只是粘贴代码。说明正在做什么以及如何解决问题。 接受最多的答案并没有太大的不同,但您并没有指出他们更新那里的答案..这是为什么?【参考方案8】:

使用扩展运算符的单线。

 const updatedData = originalData.map(x => (x.id === id ?  ...x, updatedField: 1  : x));

【讨论】:

正是我想要的! “问题”是如果我们说 id 是以随机方式创建的,你最终会得到具有相同 id 的对象【参考方案9】:

你也可以这样做

var item = ...
var items = [id:2, id:2, id:2];

var foundItem = items.filter((x) => x.id ==  item.id).pop();
foundItem = item;

items.filter((x) => x.id ==  item.id).pop()=item;

 

【讨论】:

以上是关于如何在对象数组中查找和更新值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Jquery 在数组中查找对象值?

如何获取数组里对象的某个值

如何在 JavaScript 中的对象数组中查找值?

js如何查找数组中是不是存在某个值

js如何查找数组中是不是存在某个值

js如何查找数组中是不是存在某个值