1

I need to loop through object and change exactly one of its non-true properties to true.

var object = {a: true, b: false, c: false, d: false}

function changeOne(object) {
  for(var i in object) {
    if(object[i] !== true) {
      object[i] = true;
      break;
    }
  }
}

This seems like a really bad way to go about this. Is there a better way?

snazzybouche
  • 2,241
  • 3
  • 21
  • 51

3 Answers3

1

Your code is actually fine just that the key order of objects is not defined, so your code might set b or c or d depending on the browsers engine (very unlikely that its not b but you never know...), so you should give an order by yourself:

 function changeOne(object) {
   for(var key of ["a", "b", "c", "d"]) {
     if(object[key] !== true) {
       object[key] = true;
       break;
     }
   }
 }

If you meant "better" in the sense of "shorter":

 const changeOne = obj => ["a", "b", "c", "d"].some(key => (obj[key] !== true) && (obj[key] = true));
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

You could take the entries of the object and use Array#every for a short circuit after a changed property.

function setToTrue(object) {
    Object.entries(object).every(([k, v]) => v || !(object[k] = true));
    return object;
}

var object = { a: true, b: false, c: false, d: false };

console.log(setToTrue(object));
console.log(setToTrue(object));
console.log(setToTrue(object));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

You can iterate the keys and modify the first one that has a false value:

for (let key of Object.keys(obj)) {
    if (obj[key] !== true) {
        obj[key] = true;
        break;
    }
}

OUTPUT

{ a: true, b: true, c: false, d: false }

Explanation

Object.keys(obj) will get an array of properties defined on the object itself, while var i in object will return additional properties which are part of the prototype. An alternative would be to add a check for obj.hasOwnProperty(key).

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129