95
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] }]

Johan
  • 35,120
  • 54
  • 178
  • 293
  • @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 :) – Johan May 22 '13 at 12:38

12 Answers12

82

.map with spread (...) operator

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

Piotrek
  • 1,304
  • 8
  • 16
45

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.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
36

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);
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • this is useful only if you know you'll always have a single match – Gie Sep 28 '21 at 14:21
  • 1
    @AdiG true. If you are looking at multiple it would be better to use `map` like [this answer](https://stackoverflow.com/a/45341784/4826457) – Suraj Rao Sep 28 '21 at 14:23
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;
   }
 })
Mahima Agrawal
  • 1,315
  • 13
  • 13
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];
    }
}
David Barker
  • 14,484
  • 3
  • 48
  • 77
8
    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' }
    // ]
gildniy
  • 3,528
  • 1
  • 33
  • 23
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
}
}
SivaRajini
  • 7,225
  • 21
  • 81
  • 128
3

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

Divyanshu Rawat
  • 4,421
  • 2
  • 37
  • 53
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;
    }
Muhammed Moussa
  • 4,589
  • 33
  • 27
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);
  • 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. – Chris Strickland Nov 25 '21 at 03:04
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);
Kalpesh Dabhi
  • 760
  • 8
  • 18
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