0

I really need bettter solution for this logic:

    this.allClients.forEach(obj => {
     if(obj.status === 2) {
       this.numOfWaitingUsers.push(obj) 
     }
     if(obj.status === 1) {
      this.numOfInactiveUsers.push(obj) 
    }
    if(obj.status === 0) {
      this.numOfActiveUsers.push(obj) 
    }
    if(obj.status === 3) {
      this.numOfAClosedUsers.push(obj) 
    }
    })

This is work perfect but i need better soluiton. i know to can be better with less code.

6
  • 2
    Better than perfect?! ;-) Commented Jan 22, 2021 at 17:20
  • Why do you need a better solution? This seems fine to me. Commented Jan 22, 2021 at 17:20
  • 1
    Sprinkle some elses… Commented Jan 22, 2021 at 17:20
  • 2
    FYI, there is a Code Review Stack Exchange that may be better for this type of question :) Commented Jan 22, 2021 at 17:33
  • 1
    @GarrettMotzner when suggesting users post on CR it would be great if there was also a suggestion like "Please read the relevant help center pages like 'What topics can I ask about here?' and 'How do I ask a good question?". In the current form the code above would likely be closed as off-topic because it is missing context, which happens frequently. Commented Jan 22, 2021 at 17:36

3 Answers 3

3

One solution would be to map from the status number to the array property name, like this:

const arrayNameByStatus = {    // This could be an array, but I wasn't sure if
    0: "numOfActiveUsers",     // status codes were necessarily contiguous like
    1: "numOfInactiveUsers",   // they are in the question
    2: "numOfWaitingUsers",
    3: "numOfAClosedUsers",
};
for (const obj of this.allClients) {
    const name = arrayNameByStatus[obj.status];
    if (name) { // Remove this for an error if status is an unexpected value
        this[name].push(obj);
    }
}

Live Example:

const arrayNameByStatus = {
    0: "numOfActiveUsers",
    1: "numOfInactiveUsers",
    2: "numOfWaitingUsers",
    3: "numOfAClosedUsers",
};
class Example {
    constructor() {
        this.allClients = [
            {status: 0},
            {status: 2},
            {status: 2},
        ];
        this.numOfActiveUsers = [];
        this.numOfInactiveUsers = [];
        this.numOfWaitingUsers = [];
        this.numOfAClosedUsers = [];
    }

    method() {
        for (const obj of this.allClients) {
            const name = arrayNameByStatus[obj.status];
            if (name) {
                this[name].push(obj);
            }
        }
    }
}
const e = new Example();
e.method();
console.log(e);

But, if you're going to index by status regularly, you might consider changing the structure of your object to support that directly. For instance, you might have a userCounts property that's an object with keys 0 through 3, which would let you index in directly:

// **IF** you change the structure so that `this` has a `userCounts`
// keyed by status:
for (const obj of this.allClients) {
    const array = this.userCounts[obj.status];
    if (array) { // Remove this for an error if status is an unexpected value
        array.push(obj);
    }
}

Live Example:

class Example {
    constructor() {
        this.allClients = [
            {status: 0},
            {status: 2},
            {status: 2},
        ];
        this.userCounts = {
            0: [],
            1: [],
            2: [],
            3: [],
        };
    }

    method() {
        for (const obj of this.allClients) {
            const array = this.userCounts[obj.status];
            if (array) {
                array.push(obj);
            }
        }
    }
}
const e = new Example();
e.method();
console.log(e);

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

5 Comments

Another option would be instead of array name byStatus, go for arrayByStatus.
@GarrettMotzner - That's pretty much what I mean by the second option.
Isn't it generally bad practice to look up variables or context members dynamically? i.e. this[propName]? Makes for tracing code and finding usage of variables/context members much more difficult, making refactoring more error prone.
@GarrettMotzner I did provide a better option in my answer, I believe. Simply put a reference to each array in your map, rather than the string of the variable name. It uses no more memory, and you get better code readability and reliability
@mhodges - That's part of why I'd prefer my second suggestion above over my first. :-)
2

Honestly, the code you've posted looks perfectly fine. However, if you had lots more if statements to go through, you could optimize it like the following:

// use the corresponding status as the key to access each array
let dataContainer = {
  0: this.numOfActiveUsers,
  1: this.numOfInactiveUsers,
  2: this.numOfWaitingUsers,
  3: this.numOfAClosedUsers
}
this.allClients.forEach(obj => dataContainer[obj.status].push(obj))

3 Comments

(And obviously, @bilados, add the check on dataContainer[obj.status] if it's possible to have a status value that doesn't map to any of these arrays.)
@T.J.Crowder Yes, definitely. Make sure you know what to do with an unknown status. Should it just ignore it? Should it throw an error (does that mean your code is not aligned with the API)? etc.
Indeed, a very good point. Not doing that check may well be correct, and an advantage over their current code.
0

Use a lookup table for your status codes:

// const countNames = {0:"numOfActiveUsers", 1:"numOfInactiveUsers", 2:"numOfWaitingUsers", 3:"numOfAClosedUsers"};
const countNames = ["numOfActiveUsers", "numOfInactiveUsers", "numOfWaitingUsers", "numOfAClosedUsers"];
for (const obj of this.allClients) {
    const count = countNames[obj.status];
    if (count)
        this[count].push(obj) 
}

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.