1

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?

6
  • I'm curious why for-in for one loop but Object.keys().forEach for the other...? Commented Mar 26, 2020 at 17:05
  • @T.J.Crowder so two Object.keys() inside each other? Commented Mar 26, 2020 at 17:06
  • Right, which avoids the need for the hasOwnProperty check. It's just, it looks like an intentional choice, using for-in for the outer loop and Object.keys().forEach for the inner one. If it's not intentional, no worries, I just thought it might be. :-) Commented Mar 26, 2020 at 17:07
  • 1
    You can do it with what looks like one loop, but is really nested loops like the above. I'll add that to the answer. :-) Commented Mar 26, 2020 at 17:08
  • 1
    @T.J.Crowder Thanks a million will wait for your update in the answer. I am learning a lot :D Commented Mar 26, 2020 at 17:11

2 Answers 2

2

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.

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

5 Comments

Also can explain if there is a specific reason your outer loop is over value rather than key? what if we have two unique key with the same value?
@Learner - That doesn't matter, we'll see the value twice. But if you might really have two properties that refer to the same object, the second solution will replace them with two distinct objects.
@Learner - Apologies, I'm getting called away. If you have further follow-up questions, I'll answer them when I'm back.
Thanks should I not change the first loop to: for (const entry of Object.values(getSearchDataAllCounts.counts)) {. ???
@Learner - Doh! Yes. :-) Edited.
0

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}

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.