Steven Lu
Steven Lu

Reputation: 43427

Flatten object to array?

I'm using an object as a hash table. I'd like to quickly print out its contents (for alert() for instance). Is there anything built in to convert a hash into arrays of (key, value) pairs?

Upvotes: 8

Views: 25515

Answers (7)

Timbergus
Timbergus

Reputation: 3253

Maybe a little late, but here you have my version of the answer, updated to ES2015. I use a recursive function and it works even if there are other objects inside the main object:

function objectFlattener (object) {
  return Reflect.apply(Array.prototype.concat, [], Object.keys(object).map(key => {
    if (object[key] instanceof Object) {
      return objectFlattener(object[key]);
    }
    return `${ key }: ${ object[key] }`;
  }));
}

So changing the last return you can format the element inside your array.

Upvotes: 1

Steven Lu
Steven Lu

Reputation: 43427

I updated this some more. This is much easier to parse than even console.log because it leaves out the extra stuff that's in there like __proto__.

function flatten(obj) {
    var empty = true;
    if (obj instanceof Array) {
        str = '[';
        empty = true;
        for (var i=0;i<obj.length;i++) {
            empty = false;
            str += flatten(obj[i])+', ';
        }
        return (empty?str:str.slice(0,-2))+']';
    } else if (obj instanceof Object) {
        str = '{';
        empty = true;
        for (i in obj) {
            empty = false;
            str += i+'->'+flatten(obj[i])+', ';
        }
        return (empty?str:str.slice(0,-2))+'}';
    } else {
        return obj; // not an obj, don't stringify me
    }
}

The only thing I would do to improve this is have it indent correctly based on recursion level.

Upvotes: 5

Tim Hong
Tim Hong

Reputation: 2764

Here is my version of it. It should allow you to flatten input like below:

var input = {
   a: 'asdf',
   b: [1,2,3],
   c: [[1,2],[3,4]],
   d: {subA: [1,2]}
}

The function is like this:

    function flatten (input, output) {

      if (isArray(input)) {
        for(var index = 0, length = input.length; index < length; index++){
          flatten(input[index], output);
        }
      }
      else if (isObject(input)) {
        for(var item in input){
          if(input.hasOwnProperty(item)){
            flatten(input[item], output);
          }
        }
      }
      else {
        return output.push(input);
      }
    };

    function isArray(obj) {
      return Array.isArray(obj) || obj.toString() === '[object Array]';
    }

    function isObject(obj) {
      return obj === Object(obj);
    }

Usage is something like:

var output = []

flatten(input, output);

Then output should be the flattened array.

Upvotes: 1

KooiInc
KooiInc

Reputation: 122898

for quick & dirty use in alert you could use JSON:

alert(JSON.stringify(yourObj).replace(/,/g,'\n'));

Upvotes: 3

megakorre
megakorre

Reputation: 2223

Since you want to alert it out I assume it's not for your production version, and that old browser compatibility is not an issue.

If this is the case, then you can do this:

var myHash = ......
alert(Object.keys(myHash).map(function(key) { return [key, myHash[key]]; }));

Upvotes: 11

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385104

Not that I'm aware of. Still, you can do it yourself fairly concisely:

var obj = { a: 1, b: 2, c: 3 };
var arr = [];
for (var i in obj) {
   var e = {};
   e[i] = obj[i];
   arr.push(e);
}
console.log(arr);
// Output: [Object { a=1 }, Object { b=2 }, Object { c=3 }]

Of course, you can't alert this either, so you might as well just console.log(obj) in the first place.


You could output arrays of arrays:

var obj = { a: 1, b: 2, c: 3 };
var arr = [];
for (var i in obj) {
   arr.push([i, obj[i]]);
}
console.log(arr);
// Output: [["a", 1], ["b", 2], ["c", 3]]

alert(arr);
// Alert: a, 1, b, 2, c, 3

But, again, ew.

Upvotes: 1

m0sa
m0sa

Reputation: 10940

Use the for loop:

for (var x in yourObj)
{
    alert(yourObj[x]);
}

Upvotes: 0

Related Questions