【问题标题】:How to merge two arrays of dates and keep the order for other array如何合并两个日期数组并保持其他数组的顺序
【发布时间】:2021-09-30 12:54:08
【问题描述】:

我有这个代码:

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'];

我需要将dates1dates2 合并,并为values1values2 保持相同的顺序,为没有values 的日期添加一个0,所以结果会是这样:

var dates = ['12/2020', '1/2021', '2/2021', '3/2021'];
var values1 = ['-10000', '-2650', '0', '0'];
var values2 = ['0', '3000', '3000', '1000'];

要合并日期数组,我正在使用此代码:

var dates = dates1.concat(dates2);

我只是不知道如何为values1values2 保持相同的顺序,为无值添加 0。 有什么建议吗?谢谢!

【问题讨论】:

  • 似乎键/值解决方案更适合于此。你有没有想过用字典来代替?如果是这样,那么拦截器是什么?
  • for 循环将是一个好的开始。与.indexOf().includes().splice() 结合使用。
  • 谢谢,我会去找的
  • ['1/2021', '1/2021', '12/2020'].concat(['2/2021', '3/2021', '1/2021']) 如何返回['12/2020', '1/2021', '2/2021', '3/2021']。你的翻译坏了。
  • @NewProgrammer 您确实需要将这些数组用作 dates1dates2values1values2 和日期?正如 spyder1329 提到的那样,使用字典怎么样?如果你愿意,我可以给你举个例子。

标签: javascript date


【解决方案1】:

将算法分解为最小的步骤,然后将步骤依次排列:

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)

【讨论】:

  • 非常感谢您对我的帮助!!
  • @NewProgrammer 很高兴能帮上忙
  • 哇,再次感谢,它运行良好!
【解决方案2】:

我认为您需要的是:

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);

我不知道这是否是最好的解决方案。我会创建字典来处理数据。 我知道您需要订购日期(第一个结果是 12/2020 而不是 1/2021)。我也知道您需要将日期作为字符串,但是如果您需要将日期作为数据类型,则可以删除我将其转换回字符串的部分。

【讨论】:

    【解决方案3】:

    这是python中的解决方案,转换为javascript应该是直截了当的。 1. 为 dates1/values1 和 dates2/values2 建立一个元组列表。 2. 获取唯一日期列表。 3. 将元组列表简化为一个字典,该字典累积在日期的键上。 4. 使用日期列表和字典创建结果 value1 和 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)    
    

    输出:

    ['2020/12', '2021/01', '2021/02', '2021/03']
    [-10000.0, -2650.0, 0, 0]
    [0, 3000.0, 3000.0, 1000.0]
    

    【讨论】:

      猜你喜欢
      • 2017-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-05
      • 2021-01-29
      • 2020-08-27
      • 2022-06-13
      • 2022-11-12
      相关资源
      最近更新 更多