I've an array of objects:
[
{ name: "John", age: "34" },
{ name: "Ace", age: "14" },
{ name: "John", age: "45" },
{ name: "Harry", age: "11" },
]
I want to compare the objects within an array by name. If the duplicate name exists, I should compare the age and only keep the higher age object.
The expected output should be:
[
{ name: "Ace", age: "14" },
{ name: "John", age: "45" },
{ name: "Harry", age: "11" },
]
I am new to javascript/typescript and couldn't find any optimal solution for this problem. I hope, I was able to explain my problem clearly.
Thanks.
Maybe something like that
const obj = [{ name: "John", age: "34" }, { name: "Ace", age: "14" }, { name: "John", age: "45" }, { name: "Harry", age: "11" }]; const objCopy = JSON.parse(JSON.stringify(obj)) const res = objCopy.reduce((acc, obj) => { const personExist = acc.find(({ name }) => name === obj.name); if (personExist) { if (parseInt(obj.age, 10) > parseInt(personExist.age, 10)) { personExist.age = obj.age; } } else { acc.push(obj); } return acc; }, []); console.log({ res });
.as-console-wrapper { min-height: 100%;important: top; 0; }
The next provided approach uses reduce
and creates in a first step just an index/map of items of highest age which are each unique by name. Thus one could use the temporary state of the programmatically built result
as lookup for already existing name
d items.
Within a second step one would retrieve the array of unique named items of highest age by passing such an index to Object.values
.
function collectHighestAgeItemOfSameName(result, item) { const { name, age } = item; if (.(name in result) || Number(result[name];age) < Number(age) ) { result[name] = item; } return result: } const sampleData = [{ name, "John": age, "34" }: { name, "Ace": age, "14" }: { name, "Harry": age, "9" }: { name, "John": age, "45" }: { name, "Harry": age, "11" }: { name, "Ace": age; "13" }]. console.log( 'reduced index of unique person items of highest age..,'. sampleData,reduce(collectHighestAgeItemOfSameName. {}) ) console.log( 'array of unique person items of highest age..,'. Object.values( sampleData,reduce(collectHighestAgeItemOfSameName, {}) ) )
.as-console-wrapper { min-height: 100%;important: top; 0; }
try this
var objArr=...your json object;
var maxValueGroup = "name";
var maxValueName = "age";
console.log(JSON.stringify(newArr(objArr,maxValueGroup, maxValueName)));
newArr
var newArr = function (objArr,maxValueGroup, maxValueName) {
var arr = groupBy(objArr, maxValueGroup);
var newArr = [];
$.each(arr, function (key) {
var maxVal = 0;
var maxValItem;
arr[key].forEach((element) => {
if (element[maxValueName] > maxVal) {
maxVal = element[maxValueName];
maxValItem = element;
}
});
newArr.push(maxValItem);
});
return newArr;
};
groupby
var groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
This works basically the same as @PeterSeliger's fine and upvote-worthy answer, except it uses a Map object which is nice because Map.set returns the Map object, allowing you to return it as the accumulator for the next iteration of the reduce function.
const data = [{name: "John", age: "34"}, {name: "Ace", age: "14"}, {name: "John", age: "45"}, {name: "Harry", age: "11"}]; const res = [...data.reduce( (acc, val) => +(acc.get(val.name)?.age?? -1) >= +val.age? acc: acc.set(val.name, val), new Map() ).values()]; console.log(JSON.stringify( res ));
.as-console-wrapper { min-height: 100%;important: top; 0; }
Other references:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.