0

I have an array of objects, and I want to convert them to consume the data in a chart. Someone recommends using lodash, but I don't want to use any libraries. So here is the example of the array:

const items = [
      {
        priceChangeType: 'CL',
        hierarchy: {
          department: {
            description: 'TEXTILES',
          },
        },
      },
      {
        priceChangeType: 'PM',
        hierarchy: {
          department: {
            description: 'CLOTHES',
          },
        },
      },
      {
        priceChangeType: 'CL',
        hierarchy: {
          department: {
            description: 'TEXTILES',
          },
        },
      },
      {
        priceChangeType: 'CL',
        hierarchy: {
          department: {
            description: 'CLOTHES',
          },
        },
      },
  {
        priceChangeType: 'PM',
        hierarchy: {
          department: {
            description: 'BATH',
          },
        },
      },
  {
        priceChangeType: 'PM',
        hierarchy: {
          department: {
            description: 'TOOLS',
          },
        },
      },
    {
        priceChangeType: 'CL',
        hierarchy: {
          department: {
            description: 'TOOLS',
          },
        },
      },
   {
        priceChangeType: 'CL',
        hierarchy: {
          department: {
            description: 'TOOLS',
          },
        },
      },
    ]

And I want an output like this, and this is the format needed for the chart.

const data = [
  {name: 'TOOLS', PM: 1, CL: 2},
  {name: 'CLOTHES', PM: 1, CL: 1},
  {name: 'TEXTILES', PM: 0, CL: 2},
  {name: 'BATH', PM: 1, CL: 0},
]

This is the furthest I've come, but only the total counts.

const totalPriceChangesType = Object.entries(items.reduce((r, v, i, a, k = v.priceChangeType) => ((r[k] || (r[k] = [])).push(v), r), {})).map(
    ([key, value]) => ({
      [key] : value.length,
    }),
  )

3 Answers 3

1

You can create an object (priceChangeTypes) of all the priceChangeType initialized to 0 by mapping the array to [priceChangeType, 0] pairs, and using Object.fromEntries().

Then reduce the original array to a Map. For each new hierarchy.department.description create an entry in the Map by spreading priceChangeTypes to a new object, and increment the relevant priceChangeType.

Convert back to an array using Array.from().

const items = [{priceChangeType: 'CL',hierarchy: {department: {description: 'TEXTILES'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'CLOTHES'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TEXTILES'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'CLOTHES'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'BATH'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'TOOLS'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TOOLS'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TOOLS'}}}]

// Create an initialized counts object = { CL: 0, PM: 0 }
const priceChangeTypes = Object.fromEntries(items.map(o => [o.priceChangeType, 0]))

const result = Array.from(
  items.reduce((acc, o) => {
    const key = o.hierarchy.department.description
    
    // initialize the object for the current key if needed
    if(!acc.has(key)) acc.set(key, { ...priceChangeTypes })
    
    // increment the relevant priceChangeType
    acc.get(key)[o.priceChangeType] += 1
    
    return acc
  }, new Map()),
  ([names, values]) => ({ name, ...values }) // convert to an array
)

console.log(result)

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

Comments

1

Maybe this example can help you?

const items = [{
    priceChangeType: "CL",
    hierarchy: {
      department: {
        description: "TEXTILES"
      }
    }
  },
  {
    priceChangeType: "PM",
    hierarchy: {
      department: {
        description: "CLOTHES"
      }
    }
  },
  {
    priceChangeType: "CL",
    hierarchy: {
      department: {
        description: "TEXTILES"
      }
    }
  },
  {
    priceChangeType: "CL",
    hierarchy: {
      department: {
        description: "CLOTHES"
      }
    }
  },
  {
    priceChangeType: "PM",
    hierarchy: {
      department: {
        description: "BATH"
      }
    }
  },
  {
    priceChangeType: "PM",
    hierarchy: {
      department: {
        description: "TOOLS"
      }
    }
  },
  {
    priceChangeType: "CL",
    hierarchy: {
      department: {
        description: "TOOLS"
      }
    }
  },
  {
    priceChangeType: "CL",
    hierarchy: {
      department: {
        description: "TOOLS"
      }
    }
  }
];

// collect all possible PM, CL, etc. (example: {PM:0, CL:0})
const priceChangeTypes = items.reduce((acc, item) => (acc[item.priceChangeType] = 0, acc), {});

const total = Object.values(items.reduce((acc, item) => {
  const descriprion = item.hierarchy.department.description;
  const priceChangeType = item.priceChangeType;
  // create a new base object {name: "{description}", PM:0, CL:0, ...}
  if (!acc[descriprion]) acc[descriprion] = {
    name: descriprion,
    ...priceChangeTypes
  };
  acc[descriprion][priceChangeType]++;
  return acc;
}, {}));

console.log(total);

Comments

1

Logic

  • Generate unique types from the items array using Array.map and Set
  • Reduce the items array against the name and type
  • Add the missing type to individual nodes in the output array

const items = [{priceChangeType: 'CL',hierarchy: {department: {description: 'TEXTILES'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'CLOTHES'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TEXTILES'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'CLOTHES'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'BATH'}}},{priceChangeType: 'PM',hierarchy: {department: {description: 'TOOLS'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TOOLS'}}},{priceChangeType: 'CL',hierarchy: {department: {description: 'TOOLS'}}}];
// Generate unique types
const types = Array.from(new Set(items.map(item => item.priceChangeType)));

// Reduce the items array against the name and type
const output = items.reduce((acc, curr, index, array, name = curr.hierarchy.department.description, type = curr.priceChangeType) => {
    acc[name] = acc[name] || {};
    acc[name][type] = ++acc[name][type] || 1;
    return acc;
}, {});

// Add the missing type to each object in output
Object.entries(output).forEach(([key, value]) => types.forEach(type => output[key][type] = output[key][type] || 0))
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.