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

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

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

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


当前回答

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

  details.forEach(obj => {
                const length = obj["fleet_ids"].length || 0;
                obj.set("no_of_agents" , length)
            });

以某种方式map()返回其他细节(如'$__':InternalCache, strictMode, shardval等),这是不需要的,

其他回答

你可以使用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:

对象分配(项目[项目。findIndex(el => el)id ===项目。

作为.map()的替代:

对象。分配(项目,项目。地图(el => el)id ===项目。id?项目:el)

功能的方法:

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

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

Note

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

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内容,这将修改列表的元素,然后我们需要更新列表并将其作为列表发送回数据库。

Good news is, references are kept, so you could organize your code to get advantage of it, and think about a list as an Object with identities for free, which are integers from 0 to length -1. So every time you access any property of your Object, do it as list[i], and you don't lose reference, and original object is changed. Keep in mind that this is useful when your source of truth is only one (the Object created), and your app is always consistently consuming the same Object (not fetching several times from database and assigning it to list along the lifespan of the component).

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

{ 
  1232: { id: 1232, ...},
  asdf234asf: { id: 'asdf234asf', ...},
  ...
}

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

虽然大多数现有的答案都很好,但我想包括一个使用传统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 item = {id: 1, new: true};
let items = [{id: 1}, {id: 2}];

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

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

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

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

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

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