2

I have a 2-dimensional array that looks like this:

var myArray = [
    ['Name', 'Age', 'Profession'],
    ['John', 34, 'Teacher'],
    ['Jane', 45, 'Artist']
];

I want to transform this array to an object that looks like this:

var myObject =
{
    "Name":
    {
        "Name": "Name",
        "Age": "Age",
        "Profession": "Profession"
    }
    "John":
    {
        "Name": "John",
        "Age": 34,
        "Profession": "Teacher"
    }
    "Jane":
    {
        "Name": "Jane",
        "Age": 45,
        "Profession": "Artist"
    }
};

In another thread I came across Array.prototype.reduce() and I was able to do the following:

var myObject = myArray.reduce(function(result, currentItem) {
  result[currentItem[0]] = currentItem;
  return result;
}, {})

Logger.log(myObject);
// {John=[John, 34.0, Teacher], Jane=[Jane, 45.0, Artist], Name=[Name, Age, Profession]}

However, I don't know how to apply reduce() to get a nested object or if I need a different approach here.

Andreas

Edit:

  • I am looking for an dynamical solution, that is: I don't know beforehand how many elements my array contains or what their values are.
  • I'd prefer a solution that is faster and more elegant than iterating through all elements (if possible).
Community
  • 1
  • 1
am2124429
  • 425
  • 2
  • 6
  • 8
  • Why is the first array index part of the object? Basically all solutions will require you to iterate if it is dynamic. – epascarello Jan 25 '16 at 14:41
  • @epascarello: Not sure, if I got your question right: the usage of the names (John, Jane) both as keys and as values is just an easy example. In reality, I will create an unique key out of several values (e.g. name, date of birth and email) and use it as key in my object. – am2124429 Jan 25 '16 at 15:10
  • Looks like `['Name', 'Age', 'Profession']` is heading for a table, just looked strange you would have an entry for it. – epascarello Jan 25 '16 at 15:12

3 Answers3

2

A solution with reduce and an object and some nested properties.

var myArray = [['Name', 'Age', 'Profession'], ['John', 34, 'Teacher'], ['Jane', 45, 'Artist']],
    result = myArray.reduce(function (r, a) {

        // get the first element ('Name', 'John', 'Jane') of myArray and take it as a key
        // for the object. generate a new object if there is no object available
        // read here: r.Name = r.Name || {}
        r[a[0]] = r[a[0]] || {};

        // iterate over ['Name', 'Age', 'Profession']
        myArray[0].forEach(function (b, i) {

            // assign the according value to the according property of the object
            // read here: r.Name.Name = 'Name'
            // next       r.Name.Age = 'Age'
            r[a[0]][b] = a[i];
        });
        return r;
    }, {});

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • This works fine, thank you. But I'm still trying to figure out what it does. Can you add a few words about what is the idea behind the code? – am2124429 Jan 25 '16 at 14:17
1
myArray.reduce(
function ( r, a )
{
    var row = a.reduce(
        function ( rr, cc, i )
        {
            rr[ myArray[ 0 ][ i ] ] = cc;
            return rr;
        }, {} );

    r[ a[ 0 ] ] = row;
    return r;
}, {} );

The idea is that do the same reduce at each row.

var myArray = [
  ['Name', 'Age', 'Profession'],
  ['John', 34, 'Teacher'],
  ['Jane', 45, 'Artist']
];

var result = myArray.reduce(
  function(r, a) {
    var row = a.reduce(
      function(rr, cc, i) {
        rr[myArray[0][i]] = cc;
        return rr;
      }, {});

    r[a[0]] = row;
    return r;
  }, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
g.sui
  • 1,550
  • 3
  • 15
  • 20
0

I think that the easiest way to do this could be using map function

var myArray = [
    ['Name', 'Age', 'Profession'],
    ['John', 34, 'Teacher'],
    ['Jane', 45, 'Artist']
];

var myObjects = myArray.map(function(el) { 
    return { 
        'Name': el[0],
        'Age': el[1],
        'Profession': el[2]
    } 
});

The other way is to just use on for statement

for(int i=1;myArray.length;i++)
{
    var el = myArray[i];
    myObjects2[el[0]] = { 
        'Name': el[0],
        'Age': el[1],
        'Profession': el[2]
    }
}
suvroc
  • 3,058
  • 1
  • 15
  • 29
  • 1
    indeed. Pay attention that `array.prototype.map` is not available on IE8 and earlier versions ([source](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Browser_compatibility)). – Mehdi Jan 25 '16 at 13:08
  • you generate an array, not an object with properties for every item. – Nina Scholz Jan 25 '16 at 13:19
  • Yes I know, but this part is simply enough that I don't want to obfuscate this example. But you can do just `myObject2[el[0]] = { ... }` – suvroc Jan 25 '16 at 13:23
  • I see, but in my case, I don't know of how many elements my array consists or what they are calle. Sorry, I should have mentioned this in my question. – am2124429 Jan 25 '16 at 13:59
  • So @Nina Scholz answer would be better for you – suvroc Jan 25 '16 at 14:14