I have this code:
var dates1 = ['1/2021', '1/2021', '12/2020'];
var values1 = ['-2500', '-150', '-10000'];
var dates2 = ['2/2021', '3/2021', '1/2021'];
var values2 = ['3000', '1000', '3000'];
What I need is to merge the dates1
with dates2
, and keep the same order for values1
and values2
adding a 0 for the dates that has none values
, so the result would be this:
var dates = ['12/2020', '1/2021', '2/2021', '3/2021'];
var values1 = ['-10000', '-2650', '0', '0'];
var values2 = ['0', '3000', '3000', '1000'];
To merge the arrays of dates I'm using this code:
var dates = dates1.concat(dates2);
I just don't know how can I keep the same order for values1
and values2
adding a 0 for none values.
Any suggestion ? Thank you !
CodePudding user response:
Break down the algorithm into the smallest steps, then order the steps after each other:
const dates1 = ['1/2021', '1/2021', '12/2020'];
const values1 = ['-2500', '-150', '-10000'];
const dates2 = ['2/2021', '3/2021', '1/2021'];
const values2 = ['3000', '1000', '3000'];
// summing the arrays & keeping track of how
// the values should be ordered
const reduceArr = ({ dates, values }) => {
const reduced = dates.reduce((a, c, i) => {
if (typeof a[c] === 'undefined') a[c] = 0
a[c] = Number(values[i])
return a
}, {})
const filteredDates = [...new Set([...dates])]
const filteredValues = filteredDates.map(date => reduced[date])
return {
filteredDates,
filteredValues,
}
}
// merging the different dates arrays
const mergeDates = ({ dates1, dates2 }) => {
return [...new Set([...dates1, ...dates2])]
}
// time-sorting the merged arrays
const sortDates = ({ dates }) => {
return [...dates].sort((a, b) => {
const [m1, y1] = a.split('/')
const [m2, y2] = b.split('/')
return new Date(y1, m1, 1) - new Date(y2, m2, 1)
})
}
// mapping values based on the orders &
// adding 0 if no value is found
const mapToDates = ({ sortedDates, reducedArr }) => {
return sortedDates.map(date => {
const idx = reducedArr.filteredDates.indexOf(date)
return idx === -1 ? 0 : reducedArr.filteredValues[idx]
})
}
// actually executing the steps:
const mergedDates = mergeDates({ dates1, dates2 })
const sortedDates = sortDates({ dates: mergedDates })
const reducedArr1 = reduceArr({ dates: dates1, values: values1 })
const mapValues1 = mapToDates({ sortedDates, reducedArr: reducedArr1 })
const reducedArr2 = reduceArr({ dates: dates2, values: values2 })
const mapValues2 = mapToDates({ sortedDates, reducedArr: reducedArr2 })
console.log('mapValues1', mapValues1)
console.log('mapValues2', mapValues2)
CodePudding user response:
I think that what you need is that:
Array.prototype.unique = function() {
var a = this.concat();
for(var i=0; i<a.length; i) {
for(var j=i 1; j<a.length; j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
};
stringToDate = function(str) {
return str.substring(str.search("/") 1, str.search("/") 5) "-" (Number(str.substring(0, str.search("/"))) < 10 ? '0' : '') str.substring(0, str.search("/") ) "-15T00:00:00Z";
}
dateToString = function(dt) {
dt = new Date(dt);
return (1 dt.getMonth()) "/" dt.getFullYear() ;
}
var dates1 = [stringToDate('1/2021'), stringToDate('1/2021'), stringToDate('12/2020')];
var values1 = ['-2500', '-150', '-10000'];
var dates2 = [stringToDate('2/2021'), stringToDate('3/2021'), stringToDate('1/2021')];
var values2 = ['3000', '1000', '3000'];
var dates_out = dates1.concat(dates2).unique().sort();
var values1_out = new Array(dates_out.length);
var values2_out = new Array(dates_out.length);
dates_out.forEach((dt, i) => {
dates_out[i] = dateToString(dates_out[i]);
values1_out[i] = 0;
values2_out[i] = 0;
dates1.forEach((dt1, i1) => {
if (dt1 === dt) {
if (values1_out[i] != undefined)
values1_out[i] = values1_out[i] Number(values1[i1]);
else
values1_out[i] = Number(values1[i1]);
}
});
dates2.forEach((dt2, i2) => {
if (dt2 === dt) {
if (values2_out[i] != undefined)
values2_out[i] = values2_out[i] Number(values2[i2]);
else
values2_out[i] = Number(values2[i2]);
}
});
});
console.log(dates_out);
console.log(values1_out);
console.log(values2_out);
I don't know if this is the best solution. I would create dictionaries to work with the data. I understood that you need to order the dates (the first result being 12/2020 instead of 1/2021). I also understood that you need the dates as a string, but if you need the date as a datatype, you can remove the part where I convert it back to a string.