1

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?

5
  • where is info coming from? Commented Nov 24, 2017 at 14:18
  • Your array is an object with object property Preto that has an object property P and this has a property Algodao. What exactly you need with "nested" array? Commented Nov 24, 2017 at 14:20
  • Are the record count within attributes property is fixed to 3? or it's dynamic too? Commented Nov 24, 2017 at 14:20
  • my array does not exist my friend, i need to generate it like that. Thas is an example. Commented Nov 24, 2017 at 15:01
  • The count is dynamic, this is why is very confusing to me. Commented Nov 24, 2017 at 15:01

3 Answers 3

3

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 );

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

5 Comments

Your anwser must be right! It keeps the same order. Anyway to generate an array instead of object? And would this still work if i have more than 3 levels of nest?
it does not have to be an array, but if my initial object has just one atribute or more than 3, it collapses.
You never mentioned that level of nesting needs to be dynamic. You can extend this code to achieve the same. Give it a go and create a new question if you face any trouble doing so. Good luck!
i am trying to understand how to use .map for that, but is too much confusing for me, anyhow, if you could give me a hand, would appreciate, but if not, thanks anyway.
nevermind bro, but thanks anyway, really appreciate this community.
1

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));

Comments

1

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; }

5 Comments

hi there nina, i believe your suggestion is the one, I will try it and let you know.
Nina it worked like i expected! The only issue is that the order is reversed, and this is an issue, since it puts 'sizes' in desc order. Any ideas? Thanks!
where do you get sizes from?
'Tamanho' is sizes (portuguese), im sorry. Your solution works, but reverses the entire object. Anyway to keep the same order?
in which order do you want it? you could use reduceRight for iterating from the other side.

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.