-1

I have this array of objects:

const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];

and am trying to figure out how to change the value in a given object in this original array (do not want to make a copy of the array). I have tried this

index = 4;
indexStates.filter(o => o[index] = !o[index]);
console.log(indexStates);

but the result is

    [{"4": false}, {"3": false, "4": true}, {"4": true, "7": false}, {"1": true, "4": true}]

instead of changing the value only in {"4": false} and leaving the other objects as is. What am I doing wrong? Also, I don't want to use third party libraries for this operation.

4
  • 1
    Well, for one thing you're using filter for side effects. filter's purpose is to take an array and create a new array with some of the elements removed (filtered). Commented May 15, 2020 at 12:56
  • Well, that's close but there is a structural difference with this array of objects compared to the one in the link provided. The difference is that this array is not structured in the typical format of [{key: 4, value: false}, {key: 3, value: false}... and so I'm finding it difficult to work with because the keys are dynamic in a sense. Commented May 15, 2020 at 13:07
  • FYI: filter creates a new array with references to the old elements. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented May 15, 2020 at 13:08
  • Yeah, you'd have to do something like if (index in projects[i]) { instead of if (projects[i].value == value) {. Commented May 15, 2020 at 13:28

6 Answers 6

1

Few comments for your code:

index = 4;
indexStates.filter(o => o[index] = !o[index]);

this 'index' should be a property name, not a position in the array, and with o[index] = !o[index] its a assignment, not a predicate

Instead, Try this

var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var index = 4;
var toChange = indexStates.filter(o => Object.getOwnPropertyNames(o).filter(n => n == index)[0] !== undefined)[0];
toChange[index] = !toChange[index]

console.log(toChange);
console.log(indexStates);

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

Comments

0

What you are basically saying is: filter this array to bring you only the items that the following action:

index "4" should be assigned with the opposite value

results into true, which means that the items that do not have index 4 (meaning its false in js) will be updated too.

What you need to do is:

console.log(indexStates.map(o => o[index] !== undefined ? {[index]: !o[index]} : o))

which will return a new array for you to use.

2 Comments

Were you able to get this to work in a snippet? I'm getting this result when I run it: [{"4": true}, {"4": false}, {"4": false}, {"4": false}]
0

If you do not want to create a copy, you should go for for loop and check if the key/object exists int the current object and verify. If the value is there then negate it. Below is the snippet for the same. Hope this helps

const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];

index = "4";
const length = indexStates.length;

for(let i =0; i< length; i++) {
  let elem = indexStates[i];
  if(elem[index]) elem[index] = !elem[index]
}
console.log(indexStates);

Comments

0

If you can't make a copy of the array... then you could do this:

const getIndexOfTarget = (states, target) => {
  const value = states.find(state => Object.keys(state)[0] === target)
  return states.indexOf(value)
}

const states = [{"4": true}, {"3": false}, {"7": false}, {"1": true}];
const target = String(4)
const itemToChange = getIndexOfTarget(states, target)

states[itemToChange][target] = false // or !states[itemToChange][target]

Note I cast the index, or in this case target, to a String because that's what the key types are in the objects (you could just put "4" if you own it).

If you're going to have multiple "index" of the same value, then you'd need to swap the find with a filter.

const getIndexesOfTarget = (states, target) => {
  const values = states.filter(state => Object.keys(state)[0] === target)
  return values.map(val => states.indexOf(value))
}

const itemsToChange = getIndexesOfTarget(states, target)
itemsToChange.forEach(item => states[item][target] = !states[item][target])

2 Comments

This might not work if the desired target is available more than once in the provided array.
Correct, it definitely won't work with multiple indexes of the same value. If that's likely to be the case, a for loop would be preferable for sure.
0

I would go with a foreach approach

const indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];

indexStates.forEach(elem => {
       if(typeof elem[index] === 'undefined') return elem;
       elem[index] = !elem[index];
       return elem;
    }

Comments

0

How about forEach. You can do it like this, if I understand your question correctly:

var indexStates = [ {"4": true}, {"3": false}, {"7": false}, {"1": true} ];
var target = '4';
indexStates.forEach(val=>{
    if(Object.keys(val).includes(target)) val[target]=!val[target];
});
console.log(indexStates);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.