Daniel Gynn
Daniel Gynn

Reputation: 37

Convert an array of objects into a nested object in JavaScript

I have a JavaScript array of objects, like this:

var start = [{
  name: 'example name',
  nextItem: {}
},
{
  name: 'example name 2',
  nextItem: {}
},
{
  name: 'example name 3',
  nextItem: {}
}];

I want to convert this array into a single nested object, where the inner nextItem object of the first array item contains the whole object of the next array item. For example:

var output = {
  name: 'example name',
  nextItem: {
    name: 'example name 2',
    nextItem: {
      name: 'example name 3',
      nextItem: {}
    }
  }
}

Any ideas?

Upvotes: 2

Views: 1353

Answers (6)

Yosvel Quintero
Yosvel Quintero

Reputation: 19070

You can use Array.prototype.reduceRight().

Code:

var start = [{name: 'example name',nextItem: {}},{name: 'example name 2',nextItem: {}},{name: 'example name 3',nextItem: {}}],
    output  = start.reduceRight(function (a, c) {
      return {
        name: c.name, 
        nextItem: a
      }; 
    });

console.log(output );

Updated based on comment from @NinaScholz

Upvotes: 2

Nina Scholz
Nina Scholz

Reputation: 386578

You could use and take the returned accumulator as target for the nested object without mutating the original array.

var start = [{ name: 'example name', nextItem: {} }, { name: 'example name 2', nextItem: {} }, { name: 'example name 3', nextItem: {} }],
    result = {};

start.reduce(function (o, a) {
    o.name = a.name;
    o.nextItem = {};
    return o.nextItem;
}, result);

console.log(result);
console.log(start);

ES6 with mutating the original array.

var start = [{ name: 'example name', nextItem: {} }, { name: 'example name 2', nextItem: {} }, { name: 'example name 3', nextItem: {} }],
    result = {};

start.reduce(function (o, a) {
    Object.assign(o, a);
    return o.nextItem;
}, result);

console.log(result);
console.log(start);

Upvotes: 0

webdeb
webdeb

Reputation: 13211

Could be done with a recursive function:

function nestItems(items) {
  var currentItem = items[0];
  if (!currentItem) return {};

  return {
     name: currentItem.name,
     nextItem: nestItems(items.slice(1))
  };
}


nestItems(start);

Upvotes: 2

Steffen Schmitz
Steffen Schmitz

Reputation: 890

You can use reduce on the array to add the objects:

function appendRec(obj, newObj) {
    if (obj || obj.nextItem === {}) obj.nextItem = newObj
    else appendRec(obj.nextItem, newObj)
    return obj
}

var output = start.reduce((acc, obj) => {
    return appendRec(acc, obj)
}, { nextItem: { } }).nextItem;

Upvotes: 0

Reinstate Monica Cellio
Reinstate Monica Cellio

Reputation: 26143

There may be a more graceful way of doing it, but this will do the trick. (The trick being to start at the bottom and work your way up).

var start = [{
  name: 'example name',
  nextItem: {}
},
{
  name: 'example name 2',
  nextItem: {}
},
{
  name: 'example name 3',
  nextItem: {}
}];

var output = {};

for (var i = start.length; i > 0; i--) {
  output = { name: start[i - 1].name, nextItem: output };
}

console.log(output);

Upvotes: 0

vinoth h
vinoth h

Reputation: 531

Try this :

var start = [{
  name: 'example name',
  nextItem: {}
},
{
  name: 'example name 2',
  nextItem: {}
},
{
  name: 'example name 3',
  nextItem: {}
}];

function concat(start) {
    var output = start[0];
    temp = output;
    for(i = 1;i < start.length;i ++) {
        temp.nextItem = start[i];
        temp = temp.nextItem;
    }
    return output;
}

console.log(concat(start));

Upvotes: 0

Related Questions