102
var foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];

var filtered = $.grep(foo, function(v){
    return v.bar === 1;
});

console.log(filtered);

http://jsfiddle.net/98EsQ/

Is there any way to modify a certain objects property (like the one I'm filtering out above) without creating new arrays and/or objects?

Desired result: [{ bar: 1, baz: [11,22,33] }, { bar: 2, baz: [4,5,6] }]

1
  • @squint I was looking for a method which allowed me to "point" at a certain object and let me alter it (either in ES or jQuery). But I guess I have to do it manually with a foreach :) Commented May 22, 2013 at 12:38

12 Answers 12

90

.map with spread (...) operator

var result = foo.map(el => el.bar == 1 ? {...el, baz: [11,22,33]} : el);

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

1 Comment

I cant update "baz" based on prev value,only change prop value completely.
46

Sure, just change it:

With jQuery's $.each:

$.each(foo, function() {
    if (this.bar === 1) {
        this.baz[0] = 11;
        this.baz[1] = 22;
        this.baz[2] = 33;
        // Or: `this.baz = [11, 22, 33];`
    }
});

With ES5's forEach:

foo.forEach(function(obj) {
    if (obj.bar === 1) {
        obj.baz[0] = 11;
        obj.baz[1] = 22;
        obj.baz[2] = 33;
        // Or: `obj.baz = [11, 22, 33];`
    }
});

...or you have other looping options in this other SO answer.

Comments

37

You can use find and change its property.

let foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];

let obj = foo.find(f=>f.bar==1);
if(obj)
  obj.baz=[2,3,4];
console.log(foo);

2 Comments

this is useful only if you know you'll always have a single match
@AdiG true. If you are looking at multiple it would be better to use map like this answer
11

We can also achieve this by using Array's map function:

 foo.map((obj) => {
   if(obj.bar == 1){
     obj.baz[0] = 11;
     obj.baz[1] = 22;
     obj.baz[2] = 33;
   }
 })

Comments

10

Without jQuery and backwards compatibility

for (var i = 0; i < foo.length; i++) {
    if (foo[i].bar === 1) {
        foo[i].baz = [11,12,13];
    }
}

Comments

9
    const objArr = [
        {prop1: 'value1', prop2: 'value11'},
        {prop1: 'value2', prop2: 'value22'},
        {prop1: 'value3', prop2: 'option33'},
        {prop1: 'value4', prop2: 'option44'}
    ]

    const newObjArr = objArr.map(obj => {
            if (['value1', 'value2'].includes(obj.prop1)) {
                return {...obj, prop1: 'newValue'}
            }
            return obj
        }
    )
    
    // const responseGotten = [
    //     { prop1: 'newValue', prop2: 'value11' },
    //     { prop1: 'newValue', prop2: 'value22' },
    //     { prop1: 'value3', prop2: 'option33' },
    //     { prop1: 'value4', prop2: 'option44' }
    // ]

Comments

4

But before opting any of the mentioned techniques please keep in mind the performance challenges associated with each of the approach.

Object iterate For-In, average: ~240 microseconds.

Object iterate Keys For Each, average: ~294 microseconds.

Object iterate Entries For-Of, average: ~535 microseconds.

Reference - 3 JavaScript Performance Mistakes You Should Stop Doing

Comments

3
$.each(foo,function(index,value)
{
    if(this.bar==1)
    {
this.baz[0] = 11;
        this.baz[1] = 22;
        this.baz[2] = 33;
    }

});

but for loop is faster than $.each so u can try to use

for(var i=0; i <foo.length; i++)
{

if(foo[i].bar==1)
{
//change the code
}
}

Comments

3

you can play around:

const tasks = [ { id: 1, done: false }, { id: 2, done: false } ]
const completed_task = { id: 1, done: true }

const markCompleted = (tasks, task) => {
  const index = tasks.findIndex(t => t.id === task.id);
  tasks.splice(index, 1);
  tasks.push(task);
  return tasks;
}

console.log(tasks)
console.log(markCompleted(tasks, completed_task))

EDIT

to avoid index change:

const markCompleted = (tasks, task) => {
      const index = tasks.findIndex(t => t.id === task.id);
      tasks[index] = task;
      return tasks;
    }

Comments

2

You can make use of filter function of javascript.

obj = [
    {inActive:false, id:1},
    {inActive:false, id:2},
    {inActive:false, id: 3}
];
let nObj = obj.filter(ele => {
    ele.inActive = true;
    return ele;
});

console.log(nObj);

1 Comment

Wouldn't map be more semantically correct? You are not really filtering anything, since your intent the whole time is to return every element. Also, you're not really altering the object, either, just creating a copy that is changed. I think OP specifically said no new objects.
2

You can modify the array by using simple for loop

var foo = [{ bar: 1, baz: [1,2,3] }, { bar: 2, baz: [4,5,6] }];
for(i = 0;i < foo.length;i++){
  //Here your condition for which item you went to edit
    if(foo[i].bar == 1){
    //Here you logic for update property
        foo[i].baz= [1,11,22]
    }
}
console.log(foo);

Comments

0
let myArray = [
{ id: 1, body: "wash dishes", state: "done" },
{ id: 2, body: "wash car", state: "onGoing" },
{ id: 3, body: "wash hands", state: "done" },
]

myArray.findIndex(function(obj){  //it will search between every object in array
    if (obj.body=="wash car"){ //find the object you looking for and pass to obj
        obj.state = "done"   // you can select and update any part you want here
    }

console.log(myArray) // see the updatet array

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.