Reputation: 1195
I have an object which contains number of kilograms and some dates. What I am trying to do is to push the rows with unique dates to a new array. If there is rows containing the same date, only the one with the the highest kilogram should be pushed to the new array. If there is two dates with the same kg, only one should be chosen.
Heres how it looks like:
[{"kg":10,"date":"14/10/2019"},
{"kg":15,"date":"14/10/2019"},
{"kg":15,"date":"14/10/2019"},
{"kg":5,"date":"15/10/2019"},
{"kg":10,"date":"16/10/2019"}]
And here is how the result should be in the new array:
{"kg":15,"date":"14/10/2019"},
{"kg":5,"date":"15/10/2019"},
{"kg":10,"date":"16/10/2019"}]
Now I cant figure out how to check the kg and get the highest ones. I know that I can use "Math.max" to get the highest, but not how to use it just for the same dates. I have been trying with some foreach loops but I cant understand how I can group the dates and do the Math.max. I really need some guidance here.
Note: the language is Javascript.
Upvotes: 0
Views: 180
Reputation: 41893
You could reduce whole array using Array#reduce.
const arr = [{"kg":10, "date": "14/10/2019"},
{"kg":15, "date": "14/10/2019"},
{"kg":15, "date": "14/10/2019"},
{"kg":5, "date": "15/10/2019"},
{"kg":10, "date": "16/10/2019"}];
const o = Object.values(arr.reduce((s, a) => {
if (s[a.date]) { // check if that date already exist in the result obj
if (s[a.date].kg < a.kg) {
s[a.date] = a; // assign a new value only if has higher "kg" than current
}
} else {
s[a.date] = a; // if doesnt exist yet, assign it anyways to our obj
}
return s;
}, {}));
console.log(o);
Upvotes: 2
Reputation: 1663
I think a big part of your problem is the date formatting. try 10/14/2019 instead of 14/10/2019.
After that you can always get the values to compare by making a date object and using the getDate() method on that object will then let you do the comparisons you want.
here is a simple example that works in a one-pass for-loop. I first sort the data in case you end up having data that is out of order, but this can be removed if you are sure the dates will always be in chronological order. The way I'm able to do this in one pass is by assuming the array is sorted by date from oldest at the beginning and newest at the end.
Be sure to remember that array objects are reference types. If you need the values then make sure to make a deep enough copy.
compressArray();
function compressArray() {
var orignialArray =
[{ "kg": 12, date: new Date('10/17/2019') },
{ "kg": 11, date: new Date('10/14/2019') },
{ "kg": 15, date: new Date('10/14/2019') },
{ "kg": 5, date: new Date('10/15/2019') },
{ "kg": 15, date: new Date('10/16/2019') }];
//first sort data in case the data is out of order
orignialArray = orignialArray.sort((a, b) => a.date.getDate() - b.date.getDate());
console.log(orignialArray); //after sorting
var compressedArray = new Array();
compressedArray.push(orignialArray[0]); // seed array
let j = 0; // this will be my index of the "compressed" array
for (let i = 0; i < orignialArray.length; i++)
{
if (orignialArray[i].date.getDate() == compressedArray[j].date.getDate()) {
compressedArray[j].kg = Math.max(orignialArray[i].kg, compressedArray[j].kg);
}
else
{
j++; //move compressed array index
compressedArray[j] = orignialArray[i];
}
console.log("i: " + i + "and j: " + j);
}
console.log(compressedArray);
}
Upvotes: 0