arrays - 使用 Typescript 创建动态对象来重新组织 API 响应

标签 arrays angular typescript chart.js

解释我现在正在做什么:

这类似于我从 API 响应中获取的数据数组

responseBarDataStacked = [
    { sku: "Data 1", month: "Jun", value: 20 },
    { sku: "Data 2", month: "Jun", value: 25 },
    { sku: "Data 3", month: "Jun", value: 35 },
    { sku: "Data 4", month: "Jun", value: 10 },
    { sku: "Data 5", month: "Jun", value: 10 },
    { sku: "Data 1", month: "Jul", value: 20 },
    { sku: "Data 2", month: "Jul", value: 30 },
    { sku: "Data 3", month: "Jul", value: 15 },
    { sku: "Data 4", month: "Jul", value: 20 },
    { sku: "Data 5", month: "Jul", value: null },
    { sku: "Data 1", month: "Aug", value: 20 },
    { sku: "Data 2", month: "Aug", value: 30 },
    { sku: "Data 3", month: "Aug", value: 15 },
    { sku: "Data 4", month: "Aug", value: 20 },
    { sku: "Data 5", month: "Aug", value: 15 },
];

注意:这只是数据相似,并不意味着一直只有 5 组 sku 数据或 3 个月的数据。但要确保 sku 或月份不会为空。

我正在尝试在图表(ng2-chart)上使用此响应数据作为堆积条形图。为了使这些数据在堆积条形图上工作,我需要使用一些逻辑来格式化数据,以便获得最终数据,

{
  data: [20, 25, 35, 10, 10], label: 'Jun', stack: 'sameStack',
  data: [20, 30, 15, 20, null], label: 'Jul', stack: 'sameStack',
  data: [20, 30, 15, 20, 15], label: 'Aug', stack: 'sameStack',
}

如果您看到数据数组,它是按如下顺序排列的

data: [valueof[Data 1] for month Jun, valueof[Data 2] for month Jun, valueof[Data 3] for month Jun, valueof[Data 3] for month Jun, valueof[Data 5] for month Jun]

对于其他人来说,依此类推。

为什么是这个特定的顺序? 因为如果您在方法 formatStackedBarData() 中看到下面的 uniqueSku 已在 FCFS 中设置

["Data 1", "Data 2", "Data 3", "Data 4", "Data 5"]

这是我用来相应格式化数据的方法。

  formatStackedBarData(dataToFormat: Array<any>) {
    let uniqueMonth = [...new Set(dataToFormat.map(item => item.month))];
    let uniqueSku = [...new Set(dataToFormat.map(item => item.sku))];
    let stackedBarChartData = [];

    uniqueMonth.forEach(month => {
      let uniqueMonthData = dataToFormat
        .filter(barStackData => barStackData.month == month)
        .map(uniqueStackData => uniqueStackData.value);
      stackedBarChartData.push({
        data: uniqueMonthData,
        label: month,
        stack: 'sameStack'
      });
    });

    return {
      stackedBarChartData,
      uniqueSku
    };
  }

问题:

现在,当响应困惑或 sku 的顺序发生更改时,我无法在 stackedBarChartData 上获取适当的数据。

现在响应数据已更改

  responseBarDataStacked = [
    { sku: 'Data 1', month: 'Jun', value: 20 },
    { sku: 'Data 2', month: 'Jun', value: 25 },
    { sku: 'Data 3', month: 'Jun', value: 35 },
    { sku: 'Data 5', month: 'Jun', value: 10 },
    { sku: 'Data 1', month: 'Jul', value: 20 },
    { sku: 'Data 2', month: 'Jul', value: 30 },
    { sku: 'Data 1', month: 'Aug', value: 20 },
    { sku: 'Data 2', month: 'Aug', value: 30 },
    { sku: 'Data 3', month: 'Aug', value: 15 },
    { sku: 'Data 4', month: 'Aug', value: 20 },
    { sku: 'Data 5', month: 'Aug', value: 15 }
  ];

如你所见

  • 没有 6 月份的数据 4
  • 7 月份没有数据 3、数据 4 和数据 5

对于这种情况,stackedBarChartData 的预期值是这样的

[
  {data:[20, 25, 35, 10, null], label: 'Jun', stack: 'sameStack'},
  {data:[20, 30, null, null, null], label: 'Jun', stack: 'sameStack'},
  {data:[20, 30, 15, 15, 20], label: 'Jun', stack: 'sameStack'},
]

注意:如果您在第一个对象的数据中看到最后一个值为 null,这是因为在创建 uniquesku 时,数组将类似于,这是因为使用了 FCFS,并且数据 5 在我们的数据 4 之前出现API 响应。

["Data 1", "Data 2", "Data 3", "Data 5", "Data 4"]

为了方便,我在这里实现来测试一下。 stackblitz implementation

最佳答案

您可以使用array#mapSet获取所有唯一的sku。拥有此数组后,您可以创建一个订单对象,该对象将 sku 与索引进行映射,该索引将用于为给定 sku 值的数据赋值。 p>

现在,使用array#reduce,您可以根据月份对数据进行分组,并根据sku<填充数据/code> 值。

const dataToFormat = [ { sku: 'Data 1', month: 'Jun', value: 20 }, { sku: 'Data 2', month: 'Jun', value: 25 }, { sku: 'Data 3', month: 'Jun', value: 35 }, { sku: 'Data 5', month: 'Jun', value: 10 }, { sku: 'Data 1', month: 'Jul', value: 20 }, { sku: 'Data 2', month: 'Jul', value: 30 }, { sku: 'Data 1', month: 'Aug', value: 20 }, { sku: 'Data 2', month: 'Aug', value: 30 }, { sku: 'Data 3', month: 'Aug', value: 15 }, { sku: 'Data 4', month: 'Aug', value: 20 }, { sku: 'Data 5', month: 'Aug', value: 15 } ],
      uniqueSku = [...new Set(dataToFormat.map(item => item.sku))],
      order = Object.fromEntries(uniqueSku.map((v,i) => ([v, i]))),
      result = Object.values(dataToFormat.reduce((r, {month, value, sku}) => {
        r[month] ||= {data: Array(uniqueSku.length).fill(null), label: month, stack: 'sameStack'};
        r[month].data[order[sku]] = value;
        return r;
      },{}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

关于arrays - 使用 Typescript 创建动态对象来重新组织 API 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68039444/

相关文章:

C++ 多字符数组比较

node.js - 在 Firebase Cloud Function 中启用 Cors

javascript - 如何在 ionic 复选框中使用 ngModel?

reactjs - 使用react-router-dom成功进行身份验证后将用户重定向到他们请求的页面

events - signalR调用客户端时如何在Angular2中抛出事件

PHP:即使在检查 IsSet 后仍未定义索引

arrays - 为什么在 Go 中调用可变参数函数时不能_直接_使用数组?

arrays - R - 重新排列数组

angularjs - Node 。 npm 安装后找不到 gulp

typescript - Visual Studio Code Typescript 任务编译 - 输出编码