hawx
hawx

Reputation: 1669

Getting Nested Objects Length

I have the following object:

const object = {
  user1: {
    "article1": {}
  },
  user2: {
    "article2": {},
    "article3": {},
    "article4": {}
  },
  user3: {
    "article5": {}
  },
  user4: {
    "article6": {}
  }
};

I can count the user articles using method below.

const user1count = (object && object.user1 && Object.keys(object.user1).length) || 0
const user2count = (object && object.user2 && Object.keys(object.user2).length) || 0
const user3count = (object && object.user3 && Object.keys(object.user3).length) || 0
const user4count = (object && object.user4 && Object.keys(object.user4).length) || 0

Is there a more optimal method someone can suggest? I would prefer an object like one below.

const counts = {
  user1: 1,
  user2: 3,
  user3: 1,
  user4: 1
};

Thanks in advance.

Upvotes: 4

Views: 479

Answers (6)

Mohammad Usman
Mohammad Usman

Reputation: 39322

You can make use of Object.entries(), Object.keys() and .reduce() methods to get the desired output:

const object = {
  user1: {
    "article1": {}
  },
  user2: {
    "article2": {},
    "article3": {},
    "article4": {}
  },
  user3: {
    "article5": {}
  },
  user4: {
    "article6": {}
  }
};

const counts = Object.entries(object)
                     .reduce((r, [k, o]) => (r[k] = Object.keys(o).length, r), {});
                     
console.log(counts);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 3

Ashish
Ashish

Reputation: 410

You can use forEach loop

const object = {
  user1: {
    "article1": {}
  },
  user2: {
    "article2": {},
    "article3": {},
    "article4": {}
  },
  user3: {
    "article5": {}
  },
  user4: {
    "article6": {}
  }
};


Object.keys(object).forEach(o => {
  console.log(o, Object.keys(object[o]))
  if (typeof object[o] == 'object') {
    console.log(Object.keys(object[o]).length);
  }
})

Upvotes: 3

Nick Parsons
Nick Parsons

Reputation: 50694

You can use Object.assign() with Object.entries(). First, you can .map() the entires to objects (with the key being the user and value the number of keys in that user object) and then assign each individual object in the mapped array to a single object:

const object = {user1: { "article1": {} }, user2: { "article2": {}, "article3": {}, "article4": {} }, user3: { "article5": {} }, user4: { "article6": {} }};

const res = Object.assign(
  {}, 
  ...Object.entries(object).map(([key, obj]) => ({[key]: Object.keys(obj).length}))
);

console.log(res);

Upvotes: 1

adiga
adiga

Reputation: 35222

You could map the entries of the object. Create an array of entries with the same key and the value set the length of keys. Use Object.fromEntries() to convert the entries to an object

const object = {
  user1: {
    "article1": {}
  },
  user2: {
    "article2": {},
    "article3": {},
    "article4": {}
  },
  user3: {
    "article5": {}
  },
  user4: {
    "article6": {}
  }
};

const entries = Object.entries(object).map(([k, v]) => [k, Object.keys(v).length]),
      output =  Object.fromEntries(entries);

console.log(output)

Upvotes: 3

Tal
Tal

Reputation: 439

const counts = Object.entries(object)
    .reduce((acc, entry) => ({
        ...acc,
        [entry[0]]: Object.keys(entry[1] || {}).length
    }));

Upvotes: 1

Zohaib Ijaz
Zohaib Ijaz

Reputation: 22885

You don't need to check like this object && object.user1. Just loop on outer object keys and then find the length. Create final object using reduce.

const input = {
  user1: {
    "article1": {}
  },
  user2: {
    "article2": {},
    "article3": {},
    "article4": {}
  },
  user3: {
    "article5": {}
  },
  user4: {
    "article6": {}
  }
};

const output = Object.keys(input).reduce((prev, key) => {
   prev[key] = Object.keys(input[key]).length;
   return prev;
}, {});

console.log(output);

Upvotes: 3

Related Questions