这是一个与 Owen 和 Randy 的答案类似的版本,但它将月份名称处理分离到自己的辅助函数中。独立编写,局部变量名各不相同,但作用相同。它也被构造为单个函数调用而不是一组步骤:
const monthName = ((months) => (m) => months [m - 1])(
'01|02|03|04|05|06|07|08|09|10|11|12' .split ('|') .map (
m => new Date (`2021/${m}`).toLocaleString('default', {month: 'short'})
)
)
const transform = (xs) => {
const base = Object .fromEntries (
[...new Set(input .map (
({date}) => date .slice (3, 5)
))]
.map (month => [monthName (month), ""])
)
return Object .values (xs .reduce ((years, {date, value}) => {
const Year = date .slice (6, 10),
Month = date.slice (3, 5)
years [Year] = years [Year] || {Year, ...base}
years [Year] [monthName(Month)] = value
return years
}, {}))
}
const input = [{date: "01/01/2000", value: "1"}, {date: "01/02/2000", value: "2"}, {date: "01/01/2001", value: "2"}, {date: "01/01/2002", value: "1.5"}, {date: "01/02/2002", value: "1.6"}]
console .log (transform (input))
.as-console-wrapper {max-height: 100% !important; top: 0}
一个优点是它不会Date为每个对象调用构造函数,只需在每个日历月调用一次即可。如果您不想要区域设置字符串版本,而是一组固定的月份名称,则帮助程序可以更简单:
const monthName = ((months) => (m) => months [m - 1]) (
'Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec' .split ('|')
)
我倾向于更喜欢纯粹作为表达式而不是语句编写的函数,因此替代版本可能如下所示:
const transform = (
xs,
base = Object .fromEntries (
[...new Set (xs .map (
({date}) => date .slice (3, 5)
))]
.map (month => [monthName (month), ""])
)
) => Object .values (
xs .reduce ((a, {date, value}, _, __,
Year = date .slice (6, 10), Month = date.slice (3, 5)
) => ({
...a,
[Year]: {Year, ...(a [Year] || base), [monthName (Month)]: value}
}), {})
)
它的工作方式相同,效率稍低,但我觉得它更干净。