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


133

我有一个对象数组。我想按某个字段查找,然后对其进行更改:

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以及所有属性?
Koushik Chatterjee

Answers:


250

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

16
@georg那将返回一个新数组。
CodingIntrigue

3
=>函数在IE11中不起作用。最近被这个咬了。
Lewis Cianci

1
也许最好使用let关键字而不是var
Inus Saha

仅供参考,在某些版本的phantomJS中不起作用
Sid

1
我更喜欢@CodingIntrigue使用的更详细的方法,而不是使用map@georg使用的一线。较少的心理体操需要弄清楚正在发生的事情。值得多加一些代码。
约书亚·品特

44

我最好的方法是:

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

功能方法

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

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

1
如果原始问题是英文,请链接到英文页面。此外,本示例还假定始终找到对象。
raart's

1
您总是可以将其包装在try catch表达式中,然后...对吗?
Soldeplata Saketos

1
而且对于帖子的问题完全是字面意义,他想编辑数组中的元素。他不想知道它是否存在,因此我们假设他以前已经这样做过。
Soldeplata Saketos'5

@SoldeplataSaketos是的,您可以将其包装在中try/catch,但您不应该这样做,因为找不到元素并不是例外情况;这是标准情况,您应该通过检查的返回值来解决findIndex,然后仅在找到元素时更新数组。
韦恩

20

另一种方法是使用拼接

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)

如果只想更改项目的值,可以使用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

14

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

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

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

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

请不要只粘贴代码。解释正在做的事情以及如何解决问题。
斯宾塞

1
我认为这是最好的解决方案,因为它具有最好的性能,因为它只通过数组一次并且还更改了数组的引用,因此可以避免发生可变的情况
Ohad Sadan

6

可以使用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}]


我喜欢过滤器,因为它允许创建一个新的数组,为此也不存在不存在的条目被“删除”
pungggi

0

为我工作

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

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

1
请不要只粘贴代码。解释正在做的事情以及如何解决问题。
阿德里安·摩尔

接受度最高的答案没有太大不同,但是您并没有指向他们更新那里的答案..为什么呢?
li x

0

尽管大多数现有答案都很不错,但我想提供一个使用传统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;
  }
}

尽管我非常喜欢数组函数,但不要让它们成为工具箱中的唯一工具。如果目的是使阵列变异,则它们不是最合适的。


0

一线使用传播算子。

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.