Fernando Ferrari
Fernando Ferrari

Reputation: 586

Javascript/ES6 generate nested array from 1 level object

i do have an object coming from an API like this:

  this.Variations = [
  {
    attributes: [
      {name: "Cor", option: "Preto"},
      {name: "Tamanho", option: "P"},
      {name: "Tecido", option: "Algodao"},
    ],
    id : 1
  },
  {
    attributes: [
      {name: "Cor", option: "Preto"},
      {name: "Tamanho", option: "P"},
      {name: "Tecido", option: "Elastano"},
    ],
    id : 2
  },
  {
    attributes: [
      {name: "Cor", option: "Preto"},
      {name: "Tamanho", option: "M"},
      {name: "Tecido", option: "Algodao"},
    ],
    id : 3
  }, ...

and i have to generate a nested array from it, in order to create the experience i need, which is the user selecting attributes one by time, and loading the possible options.

I am struggling with this for a long time now and got nowhere.

I believe I need an array similar to that:

array['Preto']['P']['Algodao'] = info;
array['Preto']['P']['Elastano'] = info;
array['Preto']['M']['Algodao'] = info;

Any tips on how to do that?

Upvotes: 1

Views: 762

Answers (3)

Constantiner
Constantiner

Reputation: 14221

This code works regardless of the number of items in attributes arrays:

var Variations = [
	  {
	    attributes: [
	      {name: "Cor", option: "Preto"},
	      {name: "Tamanho", option: "P"},
	      {name: "Tecido", option: "Algodao"},
	      {name: "Foo", option: "Bar"},
	    ],
	    id : 1
	  },
	  {
	    attributes: [
	      {name: "Cor", option: "Preto"},
	      {name: "Tamanho", option: "P"},
	      {name: "Tecido", option: "Elastano"},
	    ],
	    id : 2
	  },
	  {
	    attributes: [
	      {name: "Cor", option: "Preto"},
	      {name: "Tamanho", option: "M"},
	      {name: "Tecido", option: "Algodao"},
	    ],
	    id : 3
	  }];

const getLevelValue = (rec, att, index) => index === rec.attributes.length - 1 ? rec.id : {},
	getData = variations => variations.map(rec => rec.attributes.
		reduce(({acc, current}, att, index) => 
		(current = current ?  current[att.option] = getLevelValue(rec, att, index) : 
			acc[att.option] = getLevelValue(rec, att, index), {acc, current}), 
		{acc: {}}).acc);
console.log(getData(Variations));

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

You could iterate the array and the attributes for a nested object and assign a value at the leaves.

var data = [{ attributes: [{ name: "Cor", option: "Preto" }, { name: "Tamanho", option: "P" }, { name: "Tecido", option: "Algodao" }], id: 1 }, { attributes: [{ name: "Cor", option: "Preto" }, { name: "Tamanho", option: "P" }, { name: "Tecido", option: "Elastano" }], id: 2 }, { attributes: [{ name: "Cor", option: "Preto" }, { name: "Tamanho", option: "M" }, { name: "Tecido", option: "Algodao" }], id: 3 }],
    result = {};

data.forEach(function (a) {
    a.attributes.reduce(function (r, b, i, bb) {
        return r[b.option] = i + 1 === bb.length
            ? a.id
            : r[b.option] || {};
    }, result);
});

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

Upvotes: 1

gurvinder372
gurvinder372

Reputation: 68393

Assuming that by info you meant id value, try this approach

var output = variations.map( s => ({ [s.attributes[0].option ] : 
     { [s.attributes[1].option ] : 
         { [ s.attributes[2].option] : s.id } } }) );

Demo

var variations = [{
    attributes: [{
        name: "Cor",
        option: "Preto"
      },
      {
        name: "Tamanho",
        option: "P"
      },
      {
        name: "Tecido",
        option: "Algodao"
      },
    ],
    id: 1
  },
  {
    attributes: [{
        name: "Cor",
        option: "Preto"
      },
      {
        name: "Tamanho",
        option: "P"
      },
      {
        name: "Tecido",
        option: "Elastano"
      },
    ],
    id: 2
  },
  {
    attributes: [{
        name: "Cor",
        option: "Preto"
      },
      {
        name: "Tamanho",
        option: "M"
      },
      {
        name: "Tecido",
        option: "Algodao"
      },
    ],
    id: 3
  }
];

var output = variations.map( s => ({ [s.attributes[0].option ] : { [s.attributes[1].option ] : { [ s.attributes[2].option] : s.id } } }) );

console.log( output );

Upvotes: 3

Related Questions