I want to implement a function that does the following:
groupId
attribute.groupId
if they share the same common attributes, the attributes being determined by groupIfIdentical
See function skeleton here:
function groupProductsBySharedAttributes(
products: Product[],
groupIfIdentical: (keyof Product)[],
initialGroupId: string,
) {
}
Products containing identical attributes should be grouped like this:
export function productsAreIdentical(
prod1: Product,
prod2: Product,
groupIfIdentical: (keyof Product)[],
) {
for (const key of groupIfIdentical) {
if (prod1[key] !== prod2[key]) {
return false
}
return true
}
}
Example:
const prods = [{
country: 'china',
material: 'steel',
sku: 1453
},
{
country: 'china',
material: 'steel',
sku: 4874
},
{
country: 'japan',
material: 'steel',
sku: 4874
},
]
const result = groupProductsBySharedAttributes(prods, ['country', 'material'], 1001)
result = [
{
country: 'china',
material: 'steel',
sku: 1453,
groupId: 1001
},
{
country: 'china',
material: 'steel',
sku: 4874,
groupId: 1001
},
{
country: 'japan',
material: 'steel',
sku: 4874,
groupId: 1002
}
]
In the groupProductsBySharedAttributes
function
First you will initialize a Map
object called groupIdMap
where you will store the Stringify
version of the object of the groupIfIdentical
keys of the product
as a key and groupId as a value, also you will initialize a new array called groupedProducts
of the products but after inserting the groupId
, then you will loop through the products
array check if the key
exist in the groupIdMap
, if yes, they are identical, if not save the new key
and groupId
( after increment by one ), and in both cases push in the groupedProducts
interface Product {
[key: string]: any;
}
function productsAreIdentical(
prod1: Product,
prod2: Product,
groupIfIdentical: (keyof Product)[]
): boolean {
for (const key of groupIfIdentical) {
if (prod1[key] !== prod2[key]) {
return false;
}
}
return true;
}
function groupProductsBySharedAttributes(
products: Product[],
groupIfIdentical: (keyof Product)[],
initialGroupId: string,
): Product[] {
let groupId = parseInt(initialGroupId); // Convert initialGroupId to an integer for easy incrementation
const groupedProducts: Product[] = [];
const groupIdMap = new Map<string, number>(); // Maps a stringified key to a groupId
products.forEach(product => {
let foundGroup = false;
for (const [key, id] of groupIdMap) {
const keyAttributes = JSON.parse(key);
if (productsAreIdentical(product, keyAttributes, groupIfIdentical)) {
product.groupId = id;
foundGroup = true;
break;
}
}
if (!foundGroup) {
const key = JSON.stringify(
groupIfIdentical.reduce((acc, attr) => {
acc[attr] = product[attr];
return acc;
}, {} as Partial<Product>)
);
if (!groupIdMap.has(key)) {
groupIdMap.set(key, groupId);
product.groupId = groupId;
groupId++;
}
}
groupedProducts.push(product);
});
return groupedProducts;
}
// Example usage
const prods = [
{ country: 'china', material: 'steel', sku: 1453 },
{ country: 'china', material: 'steel', sku: 4874 },
{ country: 'japan', material: 'steel', sku: 4874 }
];
const result = groupProductsBySharedAttributes(prods, ['country', 'material'], '1001');
console.log(result);