tengo este codigo:
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']; Lo que necesito es fusionar las dates1 con las dates2 y mantener el mismo orden para values1 y values2 agregando un 0 para las fechas que no tienen values , por lo que el resultado sería este:
var dates = ['12/2020', '1/2021', '2/2021', '3/2021']; var values1 = ['-10000', '-2650', '0', '0']; var values2 = ['0', '3000', '3000', '1000'];Para fusionar las matrices de fechas, estoy usando este código:
var dates = dates1.concat(dates2); Simplemente no sé cómo puedo mantener el mismo orden para values1 y values2 agregando un 0 para ninguno de los valores. Cualquier sugerencia ? Gracias !
Divide el algoritmo en los pasos más pequeños, luego ordena los pasos uno tras otro:
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)Creo que lo que necesitas es eso:
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);No sé si esta es la mejor solución. Crearía diccionarios para trabajar con los datos. Entendí que necesita ordenar las fechas (el primer resultado es 12/2020 en lugar de 1/2021). También entendí que necesita las fechas como una cadena, pero si necesita la fecha como un tipo de datos, puede eliminar la parte donde la convierto nuevamente en una cadena.
aquí está la solución en python, la conversión a javascript debería ser sencilla. 1. construya una lista de tuplas para fechas1/valores1 y fechas2/valores2. 2. Obtenga una lista de fechas únicas. 3. Reducir las listas de tuplas a un diccionario acumulativo en la clave que es la fecha. 4. Usando la lista de fechas y los diccionarios, cree la lista de valores de resultado 1 y 2.
def ReduceToDictionary(tuples): dict={} for item in tuples: key = item[0] value = item[1] if key in dict: dict[key] += float(value) else: dict[key] = float(value) return dict def BuildList(dates,dict): result_values=[] for date in dates: if date in dict: val=dict[date] result_values.append(val) else: val=0 result_values.append(val) return result_values def StrToDate(string): groups=re.match('(\d{1,2})[/](\d{4})',string) year=int(groups[2]) month=int(groups[1]) return(datetime.datetime(year,month,1)) dates1 = ['1/2021', '1/2021', '12/2020'] values1 = ['-2500', '-150', '-10000'] dates2 = ['2/2021', '3/2021', '1/2021'] values2 = ['3000', '1000', '3000'] tuple1=[(StrToDate(dates1[i]),values1[i]) for i in range(len(dates1))] tuple2=[(StrToDate(dates2[i]),values2[i]) for i in range(len(dates2))] dates=sorted(set(list(map(StrToDate,dates1))+list(map(StrToDate,dates2)))) dict1=ReduceToDictionary(tuple1) dict2=ReduceToDictionary(tuple2) result_values1=BuildList(dates,dict1) result_values2=BuildList(dates,dict2) date_string=[date.strftime("%Y/%m") for date in dates] print(date_string) print(result_values1) print(result_values2)producción:
['2020/12', '2021/01', '2021/02', '2021/03'] [-10000.0, -2650.0, 0, 0] [0, 3000.0, 3000.0, 1000.0]