1

I'm trying to get the length of many nested objects with dynamic keys in an array as the below:

Input:

{
  "a": {
    "deptAS": [
      {...}
    ],
    "deptDr": [
      {...},
      {...},
      {...},
      {...},
      {...},
      {...}
    ],
    "deptES": [
      {...},
      {...}
    ],
    "deptGW": [
      {...
      }
    ]
  },
  "b": {
    "deptDr": [
      {...},
      {...},
      {...},
      {...},
      {...}
    ],
    "deptES": [
      {...},
      {...},
      {...},
      {...}
    ],
    "deptLU": [
      {...},
      {...}
    ],
    "deptSR": [
      {...},
      {...}
    ]
  },
}

Which would return:

"a": {
  "deptAS": 1,
  "deptDr": 6
  "deptES": 2,
  "deptGW": 1
}
"b": {
  "deptDr":5,
  "deptES":4,
  "deptLU":2,
  "deptSR":2,
}

I've tried various .map and lodash functions but can't get the data out in the format required, but I suspect the solution is very simple.

There is access to Lodash in the project already so that can be used

0

4 Answers 4

2

You could take a recursive approach and check if the value is an array or not.

const
    data = { a: { deptAS: [{}], deptDr: [{}, {}, {}, {}, {}, {}], deptES: [{}, {}], deptGW: [{}] }, b: { deptDr: [{}, {}, {}, {}, {}], deptES: [{}, {}, {}, {}], deptLU: [{}, {}], deptSR: [{}, {}] } },
    getLength = object => Object.fromEntries(Object
        .entries(object)
        .map(([k, v]) => [k, v.length ?? getLength(v)])
    ),
    result = getLength(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Comments

1

With lodash, it's literally a one-liner:

result = _.mapValues(yourObject, v => _.mapValues(v, 'length'))

docs: _.mapValues

Comments

0

p = {
  "a": {
    "deptAS": [
      {}
    ],
    "deptDr": [
      {},
      {},
      {},
      {},
      {},
      {}
    ],
    "deptES": [
      {},
      {}
    ],
    "deptGW": [
      {
      }
    ]
  },
  "b": {
    "deptDr": [
      {},
      {},
      {},
      {},
      {}
    ],
    "deptES": [
      {},
      {},
      {},
      {}
    ],
    "deptLU": [
      {},
      {}
    ],
    "deptSR": [
      {},
      {}
    ]
  }
}

calcProp = function(obj){
  
    const _props = Object.keys(obj);
    var _output = {};

    _props.forEach(_p=>{
      /* this way we avoid string calculation*/
      if (obj[_p].constructor.name == "Array"){
          _output[_p] = obj[_p].length
      }
      /* this way we go thought any level*/
      if (obj[_p].constructor.name == "Object"){
          _output[_p] = calcProp(obj[_p])
      }
    })

    return _output;
}
  
d = calcProp(p);
      
console.log(d);      

Comments

0
  • Using Object#entries and Array#reduce, iterate over the object's pairs
  • For every pair, add a new entry with the key and the value as the object with counts

const obj = {
  "a": {
    "deptAS": [ {} ],
    "deptDr": [ {}, {}, {}, {}, {}, {} ],
    "deptES": [ {}, {} ],
    "deptGW": [ {} ]
  },
  "b": {
    "deptDr": [ {}, {}, {}, {}, {} ],
    "deptES": [ {}, {}, {}, {} ],
    "deptLU": [ {}, {} ],
    "deptSR": [ {}, {} ]
  }
};

const res = Object.entries(obj).reduce((acc, [key, value]) => {
  acc[key] = {};
  Object.entries(value).forEach(([prop, arr]) => { acc[key][prop] = arr.length });
  return acc;
}, {});

console.log(res);

3 Comments

for the given example, this will create 10 intermediate objects which serve no obvious purpose.
@gog why 10? what do you suggest other than modifying the main object reference?
when using reduce, modify the accumulator object directly instead of creating a new object each time.

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.