3

I need to perform filter in the array of objects to get all the keys. Although, whenever there is a obj inside of that key, I would need to get the key name and concat with the key name from the obj, so for example:

const data = [ id: 5, name: "Something", obj: { lower: True, higher: False } ]
result = ["id", "name", "obj.lower", "obj.higher"]

I could manage to do the above code, but, if there is more objs inside the data, I would need to keep adding a if condition inside of my logic, I would like to know if there is any other way, so it doesn't matter how many objects I have inside the objects, It will concat always.
The code I used from the above mention:

const itemsArray = [
      { id: 1, item: "Item 001", obj: { name: 'Nilton001', message: "Free001", obj2: { test: "test001" } } },
      { id: 2, item: "Item 002", obj: { name: 'Nilton002', message: "Free002", obj2: { test: "test002" } } },
      { id: 3, item: "Item 003", obj: { name: 'Nilton003', message: "Free003", obj2: { test: "test003" } } },
    ];

const csvData = [    
    Object.keys(itemsArray[0]),
    ...itemsArray.map(item => Object.values(item))
].map(e => e.join(",")).join("\n")

// Separating keys
let keys = []
const allKeys = Object.entries(itemsArray[0]);
for (const data of allKeys) {
    if (typeof data[1] === "object") {
        const gettingObjKeys = Object.keys(data[1]);
        const concatingKeys = gettingObjKeys.map((key) => data[0] + "." + key);        
        keys.push(concatingKeys);
    } else {
        keys.push(data[0])
    }
}

//Flating
const flattingKeys = keys.reduce((acc, val: any) => acc.concat(val), []);

What I would like to achieve, lets suppose I have this array of object:

const data = 
[
   { id: 10, obj: {name: "Name1", obj2: {name2: "Name2", test: "Test"}}}
   ...
]

Final result = ["id", "obj.name", "obj.obj2.name2", "obj.obj2.test"]

OBS: The first obj contains all the keys I need, no need to loop through other to get KEYS.

I would like to achieve, all the keys from the first object of the array, and if there is objects inside of objects, I would like to concat the obj names (obj.obj2key1)

2
  • 3
    Your data isn;t valid js ? Please add a minimal reproducible example Commented Apr 28, 2022 at 14:47
  • What do you mean? Commented Apr 28, 2022 at 14:50

5 Answers 5

3

You could map the key or the keys of the nested objects.

const
    getKeys = object => Object
        .entries(object)
        .flatMap(([k, v]) => v && typeof v === 'object'
            ? getKeys(v).map(s => `${k}.${s}`)
            : k
        ),
    getValues = object => Object
        .entries(object)
        .flatMap(([k, v]) => v && typeof v === 'object'
            ? getValues(v)
            : v
        ),
    data = { id: 1, item: "Item 001", obj: { name: 'Nilton001', message: "Free001", obj2: { test: "test001" } } },
    keys = getKeys(data),
    values = getValues(data);

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

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

3 Comments

This worked better since it doesn't check if value from key is null
Could you add a code that will do the same, although it will get the value of the items separeted by commas? [1, "Item 001", "Nilton001, "Free001]...
@NiltonSchumacherF, it is nearly the same without mapping prepending key.
2

something like this

const itemsArray = [
      { id: 1, item: "Item 001", obj: { name: 'Nilton001', message: "Free001", obj2: { test: "test001" } } },
      { id: 2, item: "Item 002", obj: { name: 'Nilton002', message: "Free002", obj2: { test: "test002" } } },
      { id: 3, item: "Item 003", obj: { name: 'Nilton003', message: "Free003", obj2: { test: "test003" } } },
    ];
    
const item = itemsArray[0];

const getAllKeys = (obj, prefix=[]) => {
 if(typeof obj !== 'object'){
   return prefix.join('.')
 }
 return Object.entries(obj).flatMap(([k, v]) => getAllKeys(v, [...prefix, k]))
}

console.log(getAllKeys(item))

Comments

0

The OP solution can be simplified by accepting a prefix param (the parent key) and a results param (defaulted to [] and passed into the recursion) to do the flattening...

let obj = { key0: 'v0', key1: { innerKey0: 'innerV0', innerInner: { deeplyNested: 'v' } }, key2: { anotherInnerKey: 'innerV' } }

function recursiveKeys(prefix, obj, result=[]) {
  let keys = Object.keys(obj);
  keys.forEach(key => {
    if (typeof obj[key] === 'object')
      recursiveKeys(key, obj[key], result);
    else
      result.push(`${prefix}.${key}`)
  });
  return result;
}

console.log(recursiveKeys('', obj))

2 Comments

For multiple objects inside objects, this didn't work.
@NiltonSchumacherF - edited to add data with multiple top-level objects and deeply nested objects. Works to the extent I understand the objective of the question.
0
function getKeys(obj) {
  return Object.keys((typeof obj === 'object' && obj) || {}).reduce((acc, key) => {
    if (obj[key] && typeof obj[key] === 'object') {
      const keys = getKeys(obj[key]);
      keys.forEach((k) => acc.add(`${key}.${k}`));
    } else {
      acc.add(key);
    }
    return acc;
  }, new Set());
}

// accumulate the keys in a set (the items of the array may
// have different shapes). All of the possible keys will be
// stored in a set
const s = itemsArray.reduce(
  (acc, item) => new Set([...acc, ...getKeys(item)]),
  new Set()
);

console.log('Keys => ', Array.from(s));

2 Comments

Could you do a fix please, in case the key is there but the value is null, I still want to get the key, although I got and null error
I believe it works for null values too. Do you have an example of a case where it fails?
0

You can use recursion as follows. Since typeof([1,3,5]) is object, we also have to confirm that value is not an array, !Array.isArray(value):

const obj = { id: 10, obj: {name: "Name1", obj2: {name2: "Name2", test: "Test"}}};

const getKeys = (o,p) => Object.entries(o).flatMap(([key,value]) => 
    typeof(value) === 'object' && !Array.isArray(value) ? 
        getKeys(value, (p?`${p}.`:"") + key) : 
        (p ? `${p}.`: "") + key
);

console.log( getKeys(obj) );

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.