Javascript ES6/ES5在数组中查找并更改

Javascript ES6/ES5在数组中查找并更改,javascript,arrays,ecmascript-6,lodash,Javascript,Arrays,Ecmascript 6,Lodash,我有一个对象数组。 我想通过某个字段查找,然后更改它: var item = {...} var items = [{id:2}, {id:2}, {id:2}]; var foundItem = items.find(x => x.id == item.id); foundItem = item; 我想让它改变原始对象。怎么用?(我不在乎它是否也是lodash格式)您可以使用查找对象数组中的索引,并根据需要替换它: var item = {...} var items = [{id:

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

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

var foundItem = items.find(x => x.id == item.id);
foundItem = item;
我想让它改变原始对象。怎么用?(我不在乎它是否也是lodash格式)

您可以使用查找对象数组中的索引,并根据需要替换它:

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;
参考

如果您不想替换为新对象,而是想复制
的字段,您可以使用
对象。分配

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

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

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

:

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

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

constmyarr=[{id:1},{id:2},{id:9}];
常数[a,b,c]=myArr;
//修改原始引用将更改数组中的对象
a、 颜色='绿色';
console.log(myArr[0].color);//输出“绿色”
这个问题通常发生在使用数据库中的列表,然后映射列表以生成HTML内容时,HTML内容将修改列表的元素,然后我们需要更新列表并将其作为列表发送回数据库

好消息是,引用是保留的,因此您可以组织代码以利用它,并将
列表
视为一个具有免费标识的对象,标识是从0到
长度-1的整数。因此,每次访问对象的任何属性时,都要按照
list[i]
的方式进行,这样就不会丢失引用,原始对象也会发生更改。请记住,如果您的真实来源只有一个(创建的对象),并且您的应用程序始终使用同一个对象(在组件的使用寿命期间,不会多次从数据库中提取并将其分配给
列表
),则此功能非常有用

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

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

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

另一种方法是使用

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

N.B:如果您使用的是反应式框架,它将更新“视图”,您的阵列“知道”您已经更新了它

答复:

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
可能有用

数组[对象{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(设i=0,l=items.length;i
虽然我非常喜欢数组函数,但不要让它们成为工具箱中的唯一工具。如果目的是改变数组,那么它们不是最合适的。

对我来说很有用

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));

@georg将返回一个新数组。=>函数在IE11中不起作用。最近被这个问题困扰了。也许最好使用
let
关键字而不是
var
仅供参考,这在phantomJSI的某些版本中不起作用。我更喜欢@codingitrigue使用更详细的方法,而不是@georg使用的一行代码
map
。弄清楚发生了什么事所需的心理训练更少了。值得额外的代码行。如果原始问题是英文的,请链接到英文页面。此外,此示例假定始终可以找到该对象。您可以始终将其包装在try-catch表达式中,然后。。。是吗?他完全直截了当地回答了波斯特的问题,他想编辑数组中的一个元素。他不想知道它是否存在,所以我们假设他以前已经这样做了。@SoldeplataSaketos是的,你可以用
try/catch
来包装它,但你不应该这样做,因为找不到元素不是特例;这是一种标准情况,您应该检查
findIndex
的返回值,然后仅在找到元素时更新数组。您较新的对象
item
是否包含
id
键?或者您介意在数组条目中包含id以及
对象的所有属性吗?我喜欢过滤器,因为它允许创建一个新数组,并且不存在“删除”的条目,请不要只是粘贴代码。解释正在做什么以及这是如何解决问题的。我认为这是最好的解决方案,因为它具有最好的性能,因为它只对阵列进行一次检查,并且还更改了阵列的引用,因此,它将避免可变situations@Spencer因此,映射在
items
数组中的每个项目上循环,并检查该项目是否具有与相同的
id
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));