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

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

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


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

我想让它改变原来的对象。怎么做?(我不在乎它是否也会在Lodash中。)

373854 次浏览

你可以使用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;
}
});

我最好的方法是:

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


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

findIndex的引用

如果你不想用new object替换,而是要复制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))

功能的方法:

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

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', ...},
...
}

这样,就不用在数组中搜索,这会消耗资源。你“只需在对象中按键访问”,这是即时的和有效的。

另一种方法是使用拼接

splice()方法通过删除或替换现有元素和/或添加新元素在适当的位置来改变数组的内容。

如果你正在使用响应式框架,它会更新“视图”,你的数组“知道”你已经更新了它。

答:

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


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

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

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


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

可以使用过滤器

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

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

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

通过遍历数组,用新对象更新数组:

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

虽然大多数现有的答案都很好,但我想包括一个使用传统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;
}
}

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

为我工作

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


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

使用展开运算符的一行程序。

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

你也可以这样做

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;


 

我还没有在答案中看到这种方法,所以这里有一个简单的小代码

let item = {id: 1, new: true};
let items = [{id: 1}, {id: 2}];


let replaced = [item, ...items.filter(i => i.id !== item.id)]

您只是将项目添加到要替换的项目筛选的原始数组中。

在我的例子中,我想找到一些元素(及其长度),并想在对象本身中添加一个新元素no_of_agents。所以,跟随确实帮助了我

  details.forEach(obj => {
const length = obj["fleet_ids"].length || 0;
obj.set("no_of_agents" , length)
});
以某种方式map()返回其他详细信息(如'$__':InternalCache,

. strictMode, shardval, etc)