如何重构和映射数组以适应 React 中指定的数据结构

How to restructure and map an array to fit into a specified data structure in 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
      }
    ]
  },
]

非常感谢您仔细阅读。如果需要任何说明,请告诉我。

这实际上只是按日期进行的 'group-by' 操作,但由于嵌套数组的关系,它的复杂程度要高一些。

下面的代码片段使用了 reduce() call to accumulate into an object using date as the grouping property, and summing using input as a secondary property. To convert the resulting object back to an array of nested objects it calls Array.from() on the Object.entries() of the returned object and maps the key and data properties using the map provided as the second parameter of Array.from(). The nested data objects are generated using a final map() 调用。

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

注意:以上依赖于 logical nullish assignment operator (??=),如果需要兼容性,可以用 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;
}