1

I would like to filter an array of objects and update some value on the filtered entries. Here is my original code, without filtering:

let obj = {
  foo: [
    {
      bar: "I should be modified",
      modify: true,
    },{
      bar: "I should not be modified",
      modify: false,
    },{
      bar: "I should be modified",
      modify: true,
    },
  ],
};

obj.foo.forEach((item, i) => {
  let newItem = Object.assign({}, item);
  newItem.bar = "I have been modified";
  obj.foo[i] = newItem;
});

console.log(obj.foo);
/* Output:
  [
    {
      bar: "I have been modified",
      modify: true,
    },{
      bar: "I have been modified",
      modify: false,
    },{
      bar: "I have been modified",
      modify: true,
    },
  ],
*/

Now I would like to replace .forEach(... with .filter(e => e.modify).forEach(.... So instead of modifying all the elements of obj.foo, only those with modify === true are modified. How can this be done without filtering again inside the forEach loop?

obj.foo.filter(e => e.modify).forEach((item, i) => {
  let newItem = Object.assign({}, item);
  newItem.bar = "I have been modified";
  obj.foo[i] = newItem; // will not work as the index i is not correct from the original array
});

console.log(obj.foo);

/* Expected output:
  [
    {
      bar: "I have been modified",
      modify: true,
    },{
      bar: "I should not be modified",
      modify: false,
    },{
      bar: "I have been modified",
      modify: true,
    },
  ],
*/

/* Actual output:
  [
    {
      bar: "I have been modified",
      modify: true,
    },{
      bar: "I have been modified",
      modify: true,
    },{
      bar: "I should be modified",
      modify: true,
    },
  ],
*/

7
  • 3
    What is the expected output here? If you filter modify , how will you change the bar property? Commented Sep 8, 2020 at 15:18
  • 3
    I think you wouldn't have to filter again in the forEach loop regardless. What's wrong with adding .filter(e => e.modify).forEach(...? Commented Sep 8, 2020 at 15:18
  • 1
    obj.foo.filter((item, i) => { if(item.modify === true) { what ever you want to change goes here; return item; } }); Commented Sep 8, 2020 at 15:21
  • 1
    If you use the filter method you will lose the correct index of the element. So without filtering you should be checking with an if statement inside the forEach callback. Commented Sep 8, 2020 at 15:22
  • 2
    you should first map it then filter with the mapped index... also, please provide your output Commented Sep 8, 2020 at 15:23

3 Answers 3

1

let obj = {
  foo: [
    {
      bar: "baz",
      modify: true,
    },{
      bar: "bad",
      modify: false,
    },{
      bar: "hello",
      modify: true,
    },
  ],
};

const {foo} = obj;

const t = foo.reduce((acc, curr) => {
  if (curr.modify) {
    curr.bar = "I have been modified";
    acc.push(curr);
  }
  return acc;
}, []);

console.log(t)

Sign up to request clarification or add additional context in comments.

2 Comments

You have a bug I think, acc.push(curr) should be outside the if statement.
Yes, if you don't need to filter the array by "modify" prop
0

This can also be done like this:

obj.foo.filter(e => e.modify).map((item) => {
  item.bar = "I have been modified"
});

I think this should help.

Comments

0

So after read all the comments, that you don't want if-statement in it and other things, then this idea comes to my mind, without changing too much of your code, why don't let each item takes it's own original index, after modified, delete the idx property:

let obj = {
  foo: [
    {
      bar: "I should be modified",
      modify: true,
    },{
      bar: "I should not be modified",
      modify: false,
    },{
      bar: "I should be modified",
      modify: true,
    },
  ],
};
let index = 0;

obj.foo.filter(e =>  ++index && e.modify && (e.idx = index)).forEach((item, i) => {
  let newItem = Object.assign({}, item);
  newItem.bar = "I have been modified";
  obj.foo[newItem.idx - 1] = newItem; 
  delete newItem.idx;
});

console.log(obj.foo);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.