0

Does anyone know how to group an array of objects by an object key and then create a new array of objects based on the grouping? For example, I have an array of Build objects as below and I want to group by products and create another object of colors and price based on that.

build = [
    {
        'Product': 'Cabinets',
        'Color': 'Blue',
    }, 
    {
        'Product': 'CounterTop',
        'Color': 'White',
    }, 
    {
        'Product': 'Cabinets',
        'Color': 'Yellow',
    }, 
    {
        'Product': 'Cabinets',
        'Color': 'Yellow',
    }
]

And I want it like this

[
  {
     'Product':'Cabinet',
     'color' : { 'Blue','Yellow' }
  },
  {
     'Product':'CounterTop',
     'color' : { 'White' }
  }
]

I wrote a code to archive it but I am not getting the result as expected.

build.forEach(pr => {
                if (pr.Product in result) {
                    result[pr['Product']]['Color'] = pr['Color'];
                }
                else {
                    result[pr['Product']] = {
                        'Product': pr['Product'],
                        'Color': pr['Color'] 
                    }
                }
            });

Above code returns

 [
  {
     'Product':'Cabinet',
     'color' : 'Yellow' 
  },
  {
     'Product':'CounterTop',
     'color' : 'White'
  }
]
5
  • 1
    You are overwriting the first occurrence with the second with result[pr['Product']]['Color'] = pr['Product']. You need to Array.push or use array spread to update any existing array assigned to Color Commented Apr 28, 2022 at 16:46
  • 1
    change Color to be an array in your output. In your example Color is an object which expects a key-value pair. Commented Apr 28, 2022 at 16:51
  • @DaveMeehan I tried .push but I am getting an error saying "push is not a function". Could you please write an example? Commented Apr 28, 2022 at 16:54
  • Hi @chris, can you please tell me how do I change Color to be an array? Commented Apr 28, 2022 at 17:01
  • Have some concerns on the expected output. 1) As pointed out by others color: { "blue", "yellow" } is not a valid structure. May be it should be: color: ["blue", "yellow"]. Next, 2) The string "Cabinets" (plural) becomes "Cabinet" in expected output. Is this a typo & it should actually be "Cabinets" in both build & expected-output?. And, finally 3) There are two "Yellow" cabinets in build - but only one in expected-output. Do you need to remove duplicates - or was it a typo? Commented Apr 28, 2022 at 17:10

3 Answers 3

1

Expecting 'color' : { 'Blue','Yellow' } in your output is wrong. Objects are key-value pairs of data.

Instead, you want color to be an array. I adjusted your code:

build.forEach(pr => {
  if (pr.Product in result) {
      result[pr['Product']]['Color'].push(pr['Color']);
  } else {
      result[pr['Product']] = {
          'Product': pr['Product'],
          'Color': [pr['Color']]
      }
  }
});

Now think about how you can prevent duplicate values in the array. @Lissy93's answer helps with that by using findIndex.

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

2 Comments

So I am debugging this code and 'if (!result[pr['Product']]['Color'])' is false every time
You are right, @Rnue. Actually, doing that check is not necessary I updated my answer, thanks
0

Here's a working version. Hope it helps :)

const builds = [
    { 'Product': 'Cabinets', 'Color': 'Blue' }, 
    { 'Product': 'CounterTop', 'Color': 'White' }, 
    { 'Product': 'Cabinets', 'Color': 'Yellow' }, 
    { 'Product': 'Cabinets', 'Color': 'Yellow' }
];

const results = [];

builds.forEach((build) => {
  const index = results.findIndex((b) => b.Product === build.Product);
  if (index === -1) {
    results.push({Product: build.Product, Color: [ build.Color ]});
  } else {
    results[index] = {Product: build.Product, Color: [ ...results[index].Color, build.Color ]}
  }
});

console.log(results);

The main issue in your code, was that you're mixing up arrays and key-value-pairs for color. KVP's look like { color: 'red' }, whereas arrays would be: [ 'red', 'blue'].

Comments

0

Use this strategy:

  • Find unique products
  • Based on the unique products use Array#map and Array#filter to build desired data

See demo below:

const builds = [ { 'Product': 'Cabinets', 'Color': 'Blue' }, { 'Product': 'CounterTop', 'Color': 'White' }, { 'Product': 'Cabinets', 'Color': 'Yellow' }, { 'Product': 'Cabinets', 'Color': 'Yellow' } ],

      output = [...new Set(builds.map(({Product}) => Product))]
      .map(Product =>
          ({
              Product, 
              Color:builds.filter(({Product:P}) => P === Product)
              .map(({Color}) => Color)
           })
       );

console.log(output);

Comments

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.