skip to Main Content

I have to below code. I’m trying to create a grouped object thats groups by phase then by block using key value pairs.

Simplified item:

Item = {
Description: "Description of item",
Value: 199.99,
ValueComplete : 50,
Phase : "Phase 1",
Block : 1,
}

Code snippet:

var result = {};
Items.forEach(item => {
 //Phase
 var phase = item.Phase ?? 'None';
 if (!result[phase]) {
   result[phase] = [];
 }

 //Blocks
 var block = item.Block ?? 'None';
 if (!result[phase][block]) {
   result[phase][block] = []
 }

 result[phase][block].push(item);
});

Below is the results of the above code. Object is correct at the breakpoint but the phase’s length is 0 so therefor all block information is thrown away.

enter image description here

3

Answers


  1. The issue you’re facing with your code is due to the fact that you are using an array-like syntax to access properties of objects.

    Try this please:

    Items.forEach(item => {
        // Phase
        var phase = item.Phase ?? 'None';
        if (!result[phase]) {
            result[phase] = {};
        }
    
        // Blocks
        var block = item.Block ?? 'None';
        if (!result[phase][block]) {
            result[phase][block] = [];
        }
    
        result[phase][block].push(item);
    });
    
    Login or Signup to reply.
  2. You can use ??= operator to conditionally create missing phase objects and block arrays:

    const grouped = items.reduce((r, item) => (((r[item.Phase ?? 'None'] ??= {})[item.Block ?? 'None'] ??= []).push(item), r), {});
    console.log(grouped);
    <script>
    const items = [{
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 1",
        Block: 1,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 100,
        Phase: "Phase 1",
        Block: 1,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Block: 1,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 1",
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 1",
        Block: 2,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 1",
        Block: 2,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 2",
        Block: 1,
    },
    {
        Description: "Description of item",
        Value: 199.99,
        ValueComplete: 50,
        Phase: "Phase 2",
    }
    ];
    
    </script>
    Login or Signup to reply.
  3. The issue you’re facing is because you’re initializing result[phase] as an array ([]), but then you’re trying to use it as an object to store blocks.

    To fix this, you should initialize result[phase] as an object ({}) instead of an array.

    Here’s the corrected code:

      const result = {};
    Items.forEach(item => {
      // Phase
      const phase = item.Phase ?? 'None';
      if (!result[phase]) {
        result[phase] = {};  // Initialize as an object
      }
    
      // Blocks
      const block = item.Block ?? 'None';
      if (!result[phase][block]) {
        result[phase][block] = [];
      }
    
      result[phase][block].push(item);
    });
    

    With this change, the result object will have the structure:

    {
      "Phase 1": {
        "1": [Item1, Item2, ...],
        "2": [Item3, Item4, ...],
        ...
      },
      "Phase 2": {
        "1": [Item5, Item6, ...],
        ...
      },
      ...
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search