首页 > 解决方案 > 如何重构和映射数组以适应 React 中的指定数据结构

问题描述

我正在使用 reaviz 是 React 的图表工具。我正在创建一个习惯跟踪器应用程序,并希望在一系列条形图上直观地显示用户输入最后一周的数据。我的数据库中的数据结构如下:

habits = [
 { 
   habit: "Cook Dinner",
   inputs: [
     {
      input: 'Success',
      date: 'Oct 5th 21'
     },
     {
      input: 'Fail',
      date: 'Oct 6th 21'
     },
     {
      input: 'Skip',
      date: 'Oct 7th 21'
     }]
  },
  { 
   habit: "Clean House",
   inputs: [
     {
      input: 'Fail',
      date: 'Oct 5th 21'
     },
     {
      input: 'Fail',
      date: 'Oct 6th 21'
     },
     {
      input: 'Fail',
      date: 'Oct 7th 21'
    }]
  },
  { 
   habit: "Cook Dinner",
     inputs: [
     {
      input: 'Success',
      date: 'Oct 5th 21'
     },
     {
      input: 'Fail',
      date: 'Oct 6th 21'
     },
     {
      input: 'Skip',
      date: 'Oct 7th 21'
     }]
   }]

所以现在我想找出一种方法将我的数据映射到图表所需的数据结构,例如,对于上述数据,输出将是这样的。我需要计算当天有多少输入是成功、失败或跳过:

habitsMappedData = [
     {
    key: 'Oct 5th 21',
    data: [
      {
        key: 'Success',
        data: 2
      },
      {
        key: 'Fail',
        data: 1
      },
      {
        key: 'Skip',
        data: 0
      }
    ]
  },  {
    key: 'Oct 6th 21',
    data: [
      {
        key: 'Sucess',
        data: 0
      },
      {
        key: 'Fail',
        data: 3
      },
      {
        key: 'Skip',
        data: 0
      }
    ]
  },  {
    key: 'Oct 7th 21',
    data: [
      {
        key: 'Success',
        data: 0
      },
      {
        key: 'Fail',
        data: 1
      },
      {
        key: 'Skip',
        data: 2
      }
    ]
  },
]

非常感谢您浏览此内容。如果需要任何澄清,请告诉我。

标签: javascriptarraysreactjsfiltermapping

解决方案


这实际上只是按日期进行的“分组”操作,但由于嵌套数组,它涉及更多一点。

下面的代码片段使用reduce()调用来累积到使用date作为分组属性的对象中,并使用input作为辅助属性求和。要将生成的对象转换回嵌套对象的数组,它调用返回对象Array.from()的并使用提供的作为 的第二个参数Object.entries()映射keydata属性。嵌套对象是使用最终调用生成的。mapArray.from()datamap()

const habits = [ { habit: 'Cook Dinner', inputs: [ { input: 'Success', date: 'Oct 5th 21', }, { input: 'Fail', date: 'Oct 6th 21', }, { input: 'Skip', date: 'Oct 7th 21', }, ], }, { habit: 'Clean House', inputs: [ { input: 'Fail', date: 'Oct 5th 21', }, { input: 'Fail', date: 'Oct 6th 21', }, { input: 'Fail', date: 'Oct 7th 21', }, ], }, { habit: 'Cook Dinner', inputs: [ { input: 'Success', date: 'Oct 5th 21', }, { input: 'Fail', date: 'Oct 6th 21', }, { input: 'Skip', date: 'Oct 7th 21', }, ], }, ];

const habitsMappedData = Array.from(
  Object.entries(
    habits.reduce((a, { inputs }) => {
      for (const { date, input } of inputs) {
        (a[date] ??= { Success: 0, Fail: 0, Skip: 0 })[input] += 1;
      }

      return a;
    }, {})
  ),
  ([key, _data]) => ({
    key,
    data: Object.entries(_data).map(([key, data]) => ({ key, data })),
  })
);

console.log(habitsMappedData);
.as-console-wrapper { max-height: 100% !important; top: 0; }

注意:以上依赖于逻辑空赋值运算符 (??=),如果需要兼容性,可以将其替换为OR短路。

for (const { date, input } of inputs) {
  (a[date] || (a[date] = { Success: 0, Fail: 0, Skip: 0 }))[input] += 1;
}

或明确写出if

for (const { date, input } of inputs) {
  if (a[date] === undefined) {
    a[date] = { Success: 0, Fail: 0, Skip: 0 };
  }
  a[date][input] += 1;
}

推荐阅读