-2

I am currently working on a project in which I have an array of objects, each with "attribute" and "variation".

I need to group them as one object per attribute having the "attribute" and a list of "variations".

Sample Input:

[
    {
        "attribute": "Pack",
        "variation": "full"
    },
    {
        "attribute": "Size",
        "variation": "M"
    },
    {
        "attribute": "Color",
        "variation": "blue"
    },
    {
        "attribute": "Size",
        "variation": "X"
    },
    {
        "attribute": "Color",
        "variation": "red"
    },
    {
        "attribute": "Pack",
        "variation": "half"
    }
]

Expected Output:

[
    {
        "attribute": "Pack",
        "variations": ["full", "half" ]
    },
    {
        "attribute": "Size",
        "variations": ["M", "X"]
    },
    {
        "attribute": "Color",
        "variations": ["blue", "red"]
    },
]
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
Himanshu Rahi
  • 255
  • 4
  • 15
  • could you include what have you tried – Saeed Shamloo Jan 22 '22 at 13:08
  • There's no [JSON](https://www.json.org/json-en.html) in your question -> [What is the difference between JSON and Object Literal Notation?](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – Andreas Jan 22 '22 at 13:13
  • @MajedBadawi Why did you reopen the question? How is this not a duplicate [How can I group an array of objects by key?](https://stackoverflow.com/questions/40774697/how-can-i-group-an-array-of-objects-by-key)? o.O – Andreas Jan 22 '22 at 14:28
  • You even changed the title into what the the dupe target does! – Andreas Jan 22 '22 at 14:29
  • How would OP benefit from that? It's a different target schema. Not every grouping question should be marked as duplicate... If there's another duplicate please suggest. – Majed Badawi Jan 22 '22 at 14:35
  • So there's not even an attempt to solve this on their own... But there's a dupe target that would only need an additional `Object.entries()` or some minor adjustments... And yet OP gets a free solution (which also has dupe targets...). Got it... – Andreas Jan 22 '22 at 16:14

2 Answers2

1
  • Using Array#reduce, iterate over the array while updating an object accumulator where the attribute is the key and the corresponding object (attribute and variations) is the value. In every iteration, in order to update the variations, you need to check if there's already an existing record for the current attribute in acc with a variations list (you can use optional-chaining) and set a default value of an empty array (you can use nullish-coalescing-operator)
  • Using Object#values, return the list of grouped objects, each with attribute and variations

const arr = [ { "attribute": "Pack", "variation": "full" }, { "attribute": "Size", "variation": "M" }, { "attribute": "Color", "variation": "blue" }, { "attribute": "Size", "variation": "X" }, { "attribute": "Color", "variation": "red" }, { "attribute": "Pack", "variation": "half" } ];

const res = Object.values(
  arr.reduce((acc, { attribute, variation }) => ({
    ...acc,
    [attribute]: { 
      attribute, 
      variations: [...(acc[attribute]?.variations ?? []), variation] 
    }
  }), {})
);

console.log(res);
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
  • Throwing a bunch of code on OP without any explanation on how it works (you're using quite some new stuff in there) doesn't really teach/help OP or future readers. Also why the answer at all if there's a perfect duplicate for this really common type of question? – Andreas Jan 22 '22 at 13:26
  • @Andreas I added some explanations. I don't think the duplicate is quite exactly what OP is trying to achieve, it's not grouping the objects, but the variations of every attribute... – Majed Badawi Jan 22 '22 at 13:38
0

You can try this:

let inputObjs = [
    {
        "attribute": "Pack",
        "variation": "full"
    },
    {
        "attribute": "Size",
        "variation": "M"
    },
    {
        "attribute": "Color",
        "variation": "blue"
    },
    {
        "attribute": "Size",
        "variation": "X"
    },
    {
        "attribute": "Color",
        "variation": "red"
    },
    {
        "attribute": "Pack",
        "variation": "half"
    }
];

let grouped = [];
let attributeIndex = {};
let groupedIndex = 0;
for(k = 0; k < inputObjs.length;k++){
    const obj = inputObjs[k];
  const attrKey = `_${obj.attribute}`;
  if(typeof attributeIndex[attrKey] != 'undefined'){
    //console.log(grouped[attributeIndex[attrKey]].variations,grouped[attributeIndex[attrKey]].variations.indexOf(obj.variation),obj.variation);
    if(grouped[attributeIndex[attrKey]].variations.indexOf(obj.variation) == -1){
          grouped[attributeIndex[attrKey]].variations.push(obj.variation);
        }
  }else{
    attributeIndex[attrKey] = groupedIndex;
    grouped[attributeIndex[attrKey]] = {attribute:obj.attribute,variations:[]};
    grouped[attributeIndex[attrKey]].variations.push(obj.variation);
    groupedIndex += 1;
  }
  //console.log(obj);
}
console.log(grouped);
//console.log(attributeIndex);