I have object like that
const testOb = {
ReleaseName: "latest",
Products: [
{
ProductName: "WIDG",
A6Product: true,
ProductVersions: ["15.0.0"],
},
{
ProductName: "BIS",
A12Product: true,
ProductVersions: ["21.0.0"],
},
{
ProductName: "WIDG",
A6Product: true,
ProductVersions: ["11.0.0"],
},
{
ProductName: "BIS",
A6Product: true,
ProductVersions: ["15.0.0"],
},
{
ProductName: "UAB",
A12Product: true,
ProductVersions: ["15.0.0"],
},
{
ProductName: "UAB",
A12Product: true,
ProductVersions: ["1.0.0"],
},
{
ProductName: "WIDG",
A6Product: true,
ProductVersions: ["6.0.0"],
},
{
ProductName: "BIS",
A6Product: true,
ProductVersions: ["7.0.0"],
}
],
};
in result I want to get object like that
const testOb = {
ReleaseName: "latest",
Products: [
{
ProductName: "WIDG",
A6Product: true,
ProductVersions: ["15.0.0"],
},
{
ProductName: "BIS",
A12Product: true,
ProductVersions: ["21.0.0"],
},
{
ProductName: "UAB",
A12Product: true,
ProductVersions: ["15.0.0"],
}
],
};
Essentially I want to keep the unique objects in array and copy there the latest version of unique product name. I have tried looking at lodash as well and have not been able to come up with a way to do it. Any help would be much appreciated!
CodePudding user response:
You could compare the version with String#localeCompare
with options.
const
isSmaller = (a, b) => a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: 'base' }) < 0,
products = [{ ProductName: "WIDG", A6Product: true, ProductVersions: ["15.0.0"] }, { ProductName: "BIS", A12Product: true, ProductVersions: ["21.0.0"] }, { ProductName: "WIDG", A6Product: true, ProductVersions: ["11.0.0"] }, { ProductName: "BIS", A6Product: true, ProductVersions: ["15.0.0"] }, { ProductName: "UAB", A12Product: true, ProductVersions: ["15.0.0"] }, { ProductName: "UAB", A12Product: true, ProductVersions: ["1.0.0"] }, { ProductName: "WIDG", A6Product: true, ProductVersions: ["6.0.0"] }, { ProductName: "BIS", A6Product: true, ProductVersions: ["7.0.0"] }],
latests = Object.values(products.reduce((r, o) => {
if (
!r[o.ProductName] ||
isSmaller(r[o.ProductName].ProductVersions, o.ProductVersions)
) r[o.ProductName] = o;
return r;
}, {}));
console.log(latests);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
You will need to devise a comparator for version numbers. Once you have that, you can reduce the products by keying on the name, comparing the existing to the current, and finally updating if the new version is larger.
const compareVersions = (a, b) => {
const [aMaj, aMin, aPat] = a.split('\\.').map(parseInt);
const [bMaj, bMin, bPat] = b.split('\\.').map(parseInt);
return aMaj - bMaj || aMin - bMin || aPat - bPat;
}
const compareProducts = (a, b) =>
compareVersions(a.ProductVersions[0], b.ProductVersions[0]);
const testOb = {
ReleaseName: "latest",
Products: [
{ ProductName: "WIDG" , A6Product: true , ProductVersions: ["15.0.0"] },
{ ProductName: "BIS" , A12Product: true , ProductVersions: ["21.0.0"] },
{ ProductName: "WIDG" , A6Product: true , ProductVersions: ["11.0.0"] },
{ ProductName: "BIS" , A6Product: true , ProductVersions: ["15.0.0"] },
{ ProductName: "UAB" , A12Product: true , ProductVersions: ["15.0.0"] },
{ ProductName: "UAB" , A12Product: true , ProductVersions: ["1.0.0"] },
{ ProductName: "WIDG" , A6Product: true , ProductVersions: ["6.0.0"] },
{ ProductName: "BIS" , A6Product: true , ProductVersions: ["7.0.0"] }
],
};
const latest = {
...testOb,
Products: Object.values(testOb.Products.reduce((acc, product) =>
(existing =>
!existing || (existing && compareProducts(existing, product) < 0)
? { ...acc, [product.ProductName]: product }
: acc)
(acc[product.ProductName]), {}))
};
console.log(latest);
.as-console-wrapper { top: 0; max-height: 100% !important; }