1

I have stuck at a point where I want to recursively traverse all the objects in an array and get the keys of those objects in a array data structure. I know how to loop over and get the keys of the object. But the problem here is I need that recursively for flexible objects. By flexible I mean it can have any level of nested properties.

So, what I have is an array like this:

let record = [{
    "province": "string",
    "city": "string",
    "type": "alternative_address",
    "address_line1": "string",
    "post_code": "5858"
  },
  {
    "province": "string",
    "city": "string",
    "type": "alternative_address",
    "post_code": "5858",
    "embedeer": {
      "veryEmbedded": {
        "veryveryEmbeded": 'yes'
      }
    }
  }
];

And with some computation I am expecting an output like:

['province','city','type','address_line1','post_code','embedeer', 'embedeer.veryEmbedded', 'embedeer.veryEmbedded.veryveryEmbeded'];

For the effort I tried on this, I used the reduce() operation on array but I am unable to get that.

4 Answers 4

2

You need to write a recursive function that takes 2 inputs

  • object
  • prefix (undefined for first level keys)

let record = [{"province":"string","city":"string","type":"alternative_address","address_line1":"string","post_code":"5858"},{"province":"string","city":"string","type":"alternative_address","post_code":"5858","embedeer":{"veryEmbedded":{"veryveryEmbeded":"yes"}}}];

function addKeysToSet(o, p) {
  Object.keys(o).forEach(k => {
    let key = p ? p + "." + k : k; // Create the key hierarchy
    keys.add(key); // Add key to the set 
    // If the value is an object, call the function recursively 
    if(typeof o[k] === 'object') {
      addKeysToSet(o[k], key);
    }
  });
}

let keys = new Set(); // Create set of unique keys
// For each object in array, call function that adds keys to the set
record.forEach(o => addKeysToSet(o));
let result = Array.from(keys); // Create array from set
console.log(result); // logs result

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

Comments

1

You could take an iterative and recursive approach and take the power of a Set for getting unique values.

function iter(object, keys) {
    return Object
        .entries(object)
        .reduce((r, [k, v]) => r.concat(keys.concat(k).join('.'), v && typeof v === 'object'
            ? iter(v, keys.concat(k))
            : []
        ), []);        
}

var record = [{ province: "string", city: "string", type: "alternative_address", address_line1: "string", post_code: "5858" }, { province: "string", city: "string", type: "alternative_address", post_code: "5858", embedeer: { veryEmbedded: { veryveryEmbeded: 'yes' } } }],
    keys = [...record.reduce((s, o) => iter(o, []).reduce((t, v) => t.add(v), s), new Set)];

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

1 Comment

Thanks Nina for your answer. I always like your answers. They are very useful to learn. But I have used the one from the previous answer. :)
0

You can Flatten the object and then get the keys.

// form https://gist.github.com/penguinboy/762197

let record = [{"province":"string","city":"string","type":"alternative_address","address_line1":"string","post_code":"5858"},{"province":"string","city":"string","type":"alternative_address","post_code":"5858","embedeer":{"veryEmbedded":{"veryveryEmbeded":"yes"}}}];

var flattenObject = function(a) {
  var b = {};
  for (var c in a)
    if (a.hasOwnProperty(c))
      if ("object" == typeof a[c]) {
        var d = flattenObject(a[c]);
        for (var e in d) d.hasOwnProperty(e) && (b[c + "." + e] = d[e]);
      } else b[c] = a[c];
  return b;
};

console.log(flattenObject(record) )

/*
 It is also taking care of index numbers of the array. ("0.province" instead of "province" If multiple entries are passed)  
 
 */
console.info( "All keys", Object.keys(flattenObject(record) ) )

// Simple
console.info( "keys", Object.keys(flattenObject(record[1]) ) )

Comments

0

var record1 = [{"province": "string","city": "string","type": "alternative_address","address_line1": "string","post_code": "5858" },
  { "province": "string","city": "string",
    "type": "alternative_address",
    "post_code": "5858",
    "embedeer": {
      "veryEmbedded": {
        "veryveryEmbeded": 'yes'
      }
    }
  }
];

var output = [];
function getAllKeys(obj,precedor="") {
  var temp = Object.entries(obj);
  temp.forEach((el) => 
               typeof el[1] == "object" ? ( output.push(el[0]),getAllKeys(el[1],precedor==""? el[0]: precedor+"."+el[0])): output.push(precedor==""? el[0]: precedor+"."+el[0]));
}
 record1.forEach((el,i) => getAllKeys(el,""));
//To avoid duplicate entries convert array to object.
console.log(...(new Set(output)));

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.