Skip to content
Advertisement

How do I `.filter()` an array/object and return a new array with the original keys and not as an indexed array/object as filter return?

var obj = {
    
    111: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    }, 
    112: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    }, 
    113: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    }, 
    ... 
}

I want to filter all ("isActive" === 0) but keep the key set the same (which is equal to the user id) when returning the newObj:

newObj = {
    
    111: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    }, 
    113: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    }, 
    ... 
}

This is what I have now:

let newObj = Object.values(obj).filter( user => ( (obj.isActive === 0)));

which returns indexed keys

  • no for loops (unless the ES6 .forEach() is a must).
  • I would like an ES6 approach to this problem using filter/map/reduce if possible in this situation.
  • loadash approach are ok, but I still want to see a “vanilla ES6” example before
  • If I can get tip of how/where is best to learn and practice to filter arrays in all sorts of ways using these methods (loadash will be cool here too).

Advertisement

Answer

The truly FP way would be reduce with repeated object spread:

const filtered = Object.values(obj).reduce((p, e) => (!e.isActive ? {...p, [e.user_id]: e} : p), {});

const obj = {
    111: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    }, 
    112: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    }, 
    113: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    }
};
const filtered = Object.values(obj).reduce((p, e) => (!e.isActive ? {...p, [e.user_id]: e} : p), {});
console.log(filtered);
.as-console-wrapper {
  max-height: 100% !important;
}

That creates lots of unnecessary temporary objects, but adheres to FP principles (I think, I’m not “deep” on FP :-)) by not modifying objects in place.

Bending the rules a bit, we might modify a single object rather than creating lots of temporaries:

const filtered = Object.values(obj).reduce((newObj, e) => {
  if (!e.isActive) {
    newObj[e.user_id] = e;
  }
  return newObj;
}, {});

const obj = {
    111: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    }, 
    112: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    }, 
    113: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    }
};
const filtered = Object.values(obj).reduce((newObj, e) => {
  if (!e.isActive) {
    newObj[e.user_id] = e;
  }
  return newObj;
}, {});
console.log(filtered);
.as-console-wrapper {
  max-height: 100% !important;
}

(That can be written in fewer characters by abusing the comma operator, but it’s less maintainable and harder to read.)

Without the FP restriction, I’d just use a loop:

const filtered = {};
for (const e of Object.values(obj)) {
  if (!e.isActive) {
    filtered[e.user_id] = e;
  }
}

const obj = {
    111: {
        user_id: 111,
        user_name: "user111",
        isActive: 0
    }, 
    112: {
        user_id: 112,
        user_name: "use112",
        isActive: 1
    }, 
    113: {
        user_id: 113,
        user_name: "use113",
        isActive: 0
    }
};
const filtered = {};
for (const e of Object.values(obj)) {
  if (!e.isActive) {
    filtered[e.user_id] = e;
  }
}
console.log(filtered);
.as-console-wrapper {
  max-height: 100% !important;
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement