knot22
knot22

Reputation: 2768

alternative to multiple .forEach() loops for filter in Javascript

There is a use case to filter key/value pairs that have a value of zero out of the following dataset. If all the values are zero for the given key then the key/value pair is to be filtered out entirely (as is the case for keys 41521, 41530).

    const simpleData = {
        "41511": {
            "count": 0,
            "probability": 0.000017
        },
        "41521": {
            "count": 0,
            "probability": 0
        },
        "41530": {
            "count": 0,
            "probability": 0
        },
        "41540": {
            "count": 0,
            "probability": 0.000085
        },
        "41551": {
            "count": 1,
            "probability": 1
        }
    };

    acc = {};

    Object.entries(simpleData).forEach(([key, value]) => {
        acc[key] = {};
        Object.entries(value).forEach(([k, v]) => {
            if (v !== 0) acc[key][k] = v;
        });
        if (Object.keys(acc[key]).length === 0) delete acc[key];
    });

    // console.log('simpleData', simpleData);
    console.log('acc ', acc);

The current approach uses two .forEach() loops. Is there a different way to do this filtering that avoids multiple .forEach() loops?

Upvotes: 1

Views: 122

Answers (2)

Алексей Р
Алексей Р

Reputation: 7627

const simpleData = {
    "41511": {
        "count": 0,
        "probability": 0.000017
    },
    "41521": {
        "count": 0,
        "probability": 0
    },
    "41530": {
        "count": 0,
        "probability": 0
    },
    "41540": {
        "count": 0,
        "probability": 0.000085
    },
    "41551": {
        "count": 1,
        "probability": 1
    }
};

acc = {};
Object.entries(simpleData).forEach(([key, value]) => {
    tmp = Object.entries(value).filter(([, v]) => v !== 0);
    if (tmp.length !== 0) acc[key] = Object.fromEntries(tmp);
});
console.log('acc ', acc);

Upvotes: 1

ThS
ThS

Reputation: 4783

Actually multiple loops are not need as you can achieve your goal using the filter method to filter out the items where the count and probability keys equal to 0 or in other words to keep the items that have at least one key from count and probability keys that is not 0.

Here's a live demo:

const simpleData = {
    "41511": {
      "count": 0,
      "probability": 0.000017
    },
    "41521": {
      "count": 0,
      "probability": 0
    },
    "41530": {
      "count": 0,
      "probability": 0
    },
    "41540": {
      "count": 0,
      "probability": 0.000085
    },
    "41551": {
      "count": 1,
      "probability": 1
    }
  },
  /**
   * filtered array will contain the filtered data.
   * we'll only keep the items where at least one of the keys ("count" or "probability") is not equal to "0"
   */
  filtered = Object.entries(simpleData).filter(([k, v]) => v['count'] > 0 || v['probability'] > 0);

// print the result
console.log(filtered);

The above method prevents you from having multiple loops but now the filtered array no longer contain object but rather each item will be an array where the key 0 is the key from the original object (like 41511 and the key 1 is the actual data (like {"count": 0, "probability": 0.000017}.

Upvotes: 1

Related Questions