【问题标题】:How to push value into sub array without making a new entry如何在不创建新条目的情况下将值推入子数组
【发布时间】:2018-08-30 18:53:29
【问题描述】:

所以我有这两个数组:

resultList: { date: string, amount: number }[] = [];
dateList: { date: string, amounts: { amount: number }[] }[] = [];

其中一个有所有结果,我想按日期排序,因此是第二个数组。 这是我用来尝试实现此目的的代码:

this.resultList.forEach((result) => {
      let dateFound: boolean = false;
      this.dateList.forEach((date) => {
        if (result.date === date.date) {
          dateFound = true;
          return;
        }
      });
      if (dateFound == false) {
        //create new date entry in dateList
        this.dateList.push({date: result.date, amounts: []});
      }
      //find that date entry and push a value to it's sub array called amounts
      this.dateList.find((dates) => {
        return dates.date == result.date
      }).amounts.push({
        amount: result.amount
      });
    });

如果您有 3 个相同日期的结果,则输出

[
  {date: '2018-03-21', amounts: [{amount: 1}]},
  {date: '2018-03-21', amounts: [{amount: 1},{amount: 43}]},
  {date: '2018-03-21', amounts: [{amount: 1},{amount: 43}, {amount: 55}]}
]

如果您有 3 个相同日期的结果,则需要 OUTPUT

[
  {date: '2018-03-21', amounts: [{amount: 1},{amount: 43}, {amount: 55}]}
]

【问题讨论】:

  • 你能发布一个有效的输入数据吗?
  • if using lodash then _.groupBy else use lodash
  • @georg hehehe yes or yes!
  • 对我来说,代码似乎可以工作......
  • @H.B.这很奇怪,我从另一个项目中复制了这段代码,在那里我做了同样的事情,它在那里工作。所以我想我可能做错了什么,或者 find 不能那样工作。

标签: javascript arrays typescript multidimensional-array


【解决方案1】:

您可以先将reducing 数据放入一个对象,其中唯一的日期作为键,金额作为每个键的值,然后将mapping 它们放入所需输出的结构中,就像这样:

var data = [
  {date: '2018-03-21', amount: 1},
  {date: '2018-03-21', amount: 43},
  {date: '2018-03-21', amount: 41},
  {date: '2018-03-22', amount: 18},
  {date: '2018-03-23', amount: 25},
  {date: '2018-03-24', amount: 15},
  {date: '2018-03-24', amount: 25},
];

// reduce to single object with unique dates as keys, collection of amounts as values
var dateMap = data.reduce((res, curr) => {
  // if the date has not been added already
  if (!res[curr.date]) {
    // create it on the result object
    res[curr.date] = []
  }
  // push the amount into the array for the date
  res[curr.date].push({amount: curr.amount});
  return res;
}, {});

// map each key of dateMap to an object matching the desired output format
var dateList = Object.keys(dateMap).map(key => {
  return {date: key, amounts: dateMap[key]};
});

console.log(dateList);

【讨论】:

  • 工作非常整洁,谢谢!你知道为什么我的方法不起作用吗?
【解决方案2】:

我在您的 if 条件中添加了一个 else 子句并删除了 .find() 部分:

if (dateFound == false) {
  //create new date entry in dateList
  this.dateList.push({date: result.date, amounts: []});
} else {
  for (let d of this.dateList) {
    if (d.date == result.date) {
      d.amounts.push({amount: result.amount})
    }
  }
}

【讨论】:

  • 我现在觉得自己很蠢。这确实是我在这类东西中的第一种方法,但 javascript 真的让我对这种方法感到厌烦。
  • 很高兴听到您的问题得到解决 :) 发生在我们所有人身上
  • 这保持了原来的 O(n^2) 时间复杂度,不过
  • 我认为应该是this.dateList.push({date: result.date, amounts: result.amount}) - 否则你不会得到每个唯一日期第一次出现的金额
【解决方案3】:

您可以将reduce 数组转换成Map。为每个日期创建一个具有amounts 属性的对象,并用同一日期的金额值填充它。然后spreadMap.values()返回一个数组:

const data = [{"date":"2018-03-21","amount":1},{"date":"2018-03-21","amount":43},{"date":"2018-03-21","amount":41},{"date":"2018-03-22","amount":18},{"date":"2018-03-23","amount":25},{"date":"2018-03-24","amount":15},{"date":"2018-03-24","amount":25}];

const result = [...data
  .reduce((r, o) => {
    const { date, amount } = o;
  
    r.has(date) || r.set(date, { 
      date, 
      amounts: [] 
    });
    
    r.get(date).amounts.push({ amount });
    
    return r;
  }, new Map())
  .values()
];

console.log(result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 2021-09-08
    • 2022-11-20
    • 1970-01-01
    相关资源
    最近更新 更多