javascript 转换 github api 打卡数据

javascript transform github api punchcard data

我需要根据 Github API 调用提供的数据用 D3.js 创建一个条形图:

GET /repos/:username/:repository/stats/punch_card

响应是一个具有以下结构的数组:

Each array contains the day number, hour number, and number of commits:

0-6: Sunday - Saturday 0-23: Hour of day Number of commits

For example, [2, 14, 25] indicates that there were 25 total commits, during the 2:00pm hour on Tuesdays. All times are based on the time zone of individual commits.

Status: 200 OK
[
  [
    0,
    0,
    5
  ],
  [
    0,
    1,
    43
  ],
  (...)
  [
    6,
    22,
    21
  ], 
  [
    6,
    23,
    11
  ]
]

我需要的是转换此数据和 return 另一个数组,该数组将按天和小时对所有这些信息进行分组。我知道我需要使用 .map(), .filter() ... 但我以前没有函数式编程的经验,我在这里很迷茫。感谢任何帮助。

鉴于上面的示例,我需要 return 2 个不同的数组(绘制两个不同的条形图),如下所示:

commitsByDay = [48, ..., 33] (sum of commits by first element)

commitsByHour = [5, 43, ..., 21, 11] (sum of commits by second element)

谢谢

一种方法是使用reduce(参考here)。

reduce 函数将对数组中的每个元素应用 reducer 函数。这个函数有两个参数:accumulatorcurrentValue.

最基本的归约得到列表的总和。这是一个例子:

let numbers = [1,2,3,4,5];
let sum = numbers.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
});
sum; //has a value of (1 + 2) + 3) + 4) + 5 = 15

本质上,reducer 是为数组中的每个元素调用的。每次,currentValue等于当前数组元素,accumulator等于上一次调用的return值。 reduce 函数的输出是减速器的最后一个 return 值。

对于您的问题,累加器需要跟踪每个周期(天或小时)的总和,而不是总和。为此,累加器应该从一个空数组开始,然后在每次调用 reducer 时进行更新。假设数据在名为 response 的变量中,这是按天获取数据的方式:

let commitsByDay = response.reduce(
  (accumulator, currentValue) => {
    // "currentValue" is an individual record, stored as [day, hour, commits]
    let day = currentValue[0]; 
    let commits = currentValue[2];

    // "accumulator" contains the number of commits per day in an array
    // The index of the array corresponds to the day number
    // We will update the accumulator to contain the data from "currentValue"
    accumulator[day] = (accumulator[day] || 0) + commits;

    // The "accumulator" must be returned
    return accumulator;
  }, 
  [] // The initial value for "accumulator" is an empty array
);
commitsByDay; // Now contains the final value of "accumulator"

备注

虽然 reduce 很好,但您 不需要 使用它。您可以使用 for 循环完成完全相同的事情。通常,reducemapfilter 使代码更具可读性,但它们不是 必需的