Home > Software design >  How I can count values and obtain another array structure?
How I can count values and obtain another array structure?

Time:01-06

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,
    }),
  )

CodePudding user response:

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);

CodePudding user response:

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);

CodePudding user response:

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)

  •  Tags:  
  • Related