Home > Back-end >  JS Array Reduce to count Object Values with a Multiple Matching Keys
JS Array Reduce to count Object Values with a Multiple Matching Keys

Time:09-29

I have an array like this:

var objects = [{
    cat: "Fixtures"
    name: "brilliance_denali_(best)"
    shadowColor: "warmWhite"
    subCat: "Spot & Bullet Lights"
    title: "Brilliance Denali (Best)"
    wattage: {upPrice: 10, value: '10W'}
},
{
    cat: "Fixtures"
    name: "brilliance_denali_(best)"
    shadowColor: "warmWhite"
    subCat: "Spot & Bullet Lights"
    title: "Brilliance Denali (Best)"
    wattage: {upPrice: 10, value: '10W'}
},
{
    cat: "Fixtures"
    name: "brilliance_denali_(best)"
    shadowColor: "red"
    subCat: "Spot & Bullet Lights"
    title: "Brilliance Denali (Best)"
    wattage: {upPrice: 12, value: '12W'}
},
{
    cat: "Fixtures"
    name: "bullet_lights"
    shadowColor: "blue"
    subCat: "Lights"
    title: "Bullet Lights"
    wattage: {upPrice: 28, value: '10W'}
}]

And I want to reduce this array based on "cat" and then inside cat is "subCat" and then inside the objects where I want to reduce them with additional "COUNT" key if they have the same "name", "shadowColor" and "wattage value". So in total the output array should look like this:

var formattedObjects = [
    {
        cat: 'Fixtures',
        children: [
            {
                subCat: 'Lights',
                childres: [
                    {
                        cat: "Fixtures"
                        name: "bullet_lights"
                        shadowColor: "blue"
                        subCat: "Lights"
                        title: "Bullet Lights"
                        wattage: {upPrice: 28, value: '10W'},
                        count: 1     <-- COUNT BASED ON SAME : NAME && SHADOWCOLOR && WATTAGE VALUE
                    }
                ]
            }, {
                subCat: 'Spot & Bullet Lights',
                childres: [
                    {
                        {
                            cat: "Fixtures"
                            name: "brilliance_denali_(best)"
                            shadowColor: "warmWhite"
                            subCat: "Spot & Bullet Lights"
                            title: "Brilliance Denali (Best)"
                            wattage: {upPrice: 10, value: '10W'},
                            count: 2         <-- COUNT BASED ON SAME : NAME && SHADOWCOLOR && WATTAGE VALUE
                        },
                        {
                            cat: "Fixtures"
                            name: "brilliance_denali_(best)"
                            shadowColor: "red"
                            subCat: "Spot & Bullet Lights"
                            title: "Brilliance Denali (Best)"
                            wattage: {upPrice: 12, value: '12W'},
                            count: 1        <-- COUNT BASED ON SAME : NAME && SHADOWCOLOR && WATTAGE VALUE
                        }

                    }
                ]
            }
        ]
    }
]

So far, I was able to reduce it based on "subCat" and "cat" each having nested children but I am not sure how should I add the counts inside that and remove objects having same "name", "sahdowColor" and "wattage value". This is how my reducer looks like without count:

const formatedObjects = objects.reduce((list, item) => {
    const { cat, subCat } = item;
    const hasList = !!list?.[cat];
    const subList = list?.[cat]?.children.find(child => child.subCat === subCat)
    const value = { 
      name: item.name,
      title: item.title,
      shadowColor: item.shadowColor ? item.shadowColor : null ,
      wattage: item.wattage ? item.wattage : null
    }; // the element in data property
    if (!hasList) {
      list[cat] = { cat, children: [
        {
          subCat,
          children: [value]
        }
      ]}
    } else if (!subList){
      list[cat].children.push({ subCat, children: [value]})
    } else {
      subList.children.push(value)     
    }
    return list;
  }, {})

Any idea how should I add count in that reducer??? Thanks.

CodePudding user response:

Not sure, But is this what you are looking for?

let objects = [{ cat: "Fixtures", name: "brilliance_denali_(best)", shadowColor: "warmWhite", subCat: "Spot & Bullet Lights", title: "Brilliance Denali (Best)", wattage: { upPrice: 10, value: '10W' } }, { cat: "Fixtures", name: "brilliance_denali_(best)", shadowColor: "warmWhite", subCat: "Spot & Bullet Lights", title: "Brilliance Denali (Best)", wattage: { upPrice: 10, value: '10W' } }, { cat: "Fixtures", name: "brilliance_denali_(best)", shadowColor: "red", subCat: "Spot & Bullet Lights", title: "Brilliance Denali (Best)", wattage: { upPrice: 12, value: '12W' } }, { cat: "Fixtures", name: "bullet_lights", shadowColor: "blue", subCat: "Lights", title: "Bullet Lights", wattage: { upPrice: 28, value: '10W' } }]

let result = [], counter = {};

for (let item of objects) {
    let countId = item.name   item.shadowColor   item.wattage.value
    if (counter[countId]) {
      counter[countId].count  ;
      continue
    }
    let cat = result.find(o => o.cat == item.cat);
    if (!cat) result.push(cat = { cat: item.cat, children: [] });
    let subCat = cat.children.find(o => o.subCat == item.subCat);
    if (!subCat) cat.children.push(subCat = { subCat: item.subCat, childres: [] });
    item.count = 1
    subCat.childres.push(counter[countId] = item);
}

console.log(result)

  • Related