Learner
Learner

Reputation: 1968

Initialize an array of object with unknown keys in a better way using es6

I have an object as follows:

{
    "counts": {
        "created_by_ref": {
            "00f5c303-32c0-4f5f-ac61-bf6577a8f4ed": 1,
            "0dde2de1-7951-45b1-8bf3-013f8dbfc4ae": 1
        },
        "file.hashes.MD5": {
            "qqq": 200
        },
        "ipv4_addr.value": {
            "127.0.0.1": 200,
            "192.168.1.10": 200
        },
        "network_traffic.dst_port": {
            "xxx": 200
        },
        "network_traffic.dst_ref.resolves_to_refs.value": {
            "yyy": 200
        },
        "network_traffic.dst_ref.value": {
            "rrr": 200
        }
    }
}

I need to initialize all the values to 0 as follows:

{
    "counts": {
        "created_by_ref": {
            "00f5c303-32c0-4f5f-ac61-bf6577a8f4ed": 0,
            "0dde2de1-7951-45b1-8bf3-013f8dbfc4ae": 0
        },
        "file.hashes.MD5": {
            "qqq": 0
        },
        "ipv4_addr.value": {
            "127.0.0.1": 0,
            "192.168.1.10": 0
        },
        "network_traffic.dst_port": {
            "xxx": 0
        },
        "network_traffic.dst_ref.resolves_to_refs.value": {
            "yyy": 0
        },
        "network_traffic.dst_ref.value": {
            "rrr": 0
        }
    }
}

and all the keys except count is unknown and dynamically changing so cannot be hard code. What I did is:

  for (const key in getSearchDataAllCounts) {
    if (getSearchDataAllCounts.hasOwnProperty(key)) {
      Object.keys(getSearchDataAllCounts[key]).forEach((innerkey) => {
        getSearchDataAllCounts[key][innerkey] = 0;
      });
    }
  }

But I really think there is a better way doing it in ES6. Is there any improvement I can make to make it more es6 compatible and also do it with one loop preferebly?

Upvotes: 1

Views: 411

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074335

ES2015+ doesn't really give you much to improve that code, other than for-of and Object.values:

for (const entry of Object.values(getSearchDataAllCounts.counts)) {
  for (const key of Object.keys(entry)) {
    entry[key] = 0;
  }
}

In a comment you asked:

So we cannot do it with one loop right?

You can do it with what looks like one loop, but is really nested loops like the above (more loops, in fact):

for (const [key, entry] of Object.entries(getSearchDataAllCounts.counts)) {
    getSearchDataAllCounts.counts[key] = Object.fromEntries(
      Object.keys(entry).map(key => [key, 0])
    );
}

That uses Object.entries to get an array of [key, value] pairs for the outer object, then replaces that object with a new object we create by

  • Getting its keys
  • Mapping them to [key, 0] entries
  • Using Object.fromEntries to create an object from those entries

There's an important difference there, though: It creates new objects to store on the properties of the outermost object. The first one just updates the properties of the existing objects.

Upvotes: 2

xdeepakv
xdeepakv

Reputation: 8125

You dont need ES6. Using JSON replacer, u can do it on the tree traversing.

Util

const zero = obj =>
   JSON.parse(JSON.stringify(obj, (_, v) => (typeof v === "object" ? v : 0)));

console.log(zero(d));

How to use

console.log(zero(d));

var d = {
  counts: {
    created_by_ref: {
      "00f5c303-32c0-4f5f-ac61-bf6577a8f4ed": 1,
      "0dde2de1-7951-45b1-8bf3-013f8dbfc4ae": 1
    },
    "file.hashes.MD5": {
      qqq: 200
    },
    "ipv4_addr.value": {
      "127.0.0.1": 200,
      "192.168.1.10": 200
    },
    "network_traffic.dst_port": {
      xxx: 200
    },
    "network_traffic.dst_ref.resolves_to_refs.value": {
      yyy: 200
    },
    "network_traffic.dst_ref.value": {
      rrr: 200
    }
  }
};
const zero = obj => JSON.parse(JSON.stringify(obj, (_, v) => (typeof v === "object" ? v : 0)));
console.log(zero(d));
.as-console-row {color: blue!important}

Upvotes: 0

Related Questions