2

我有下表数据:

日期 价值
2000 年 1 月 1 日 1
2000 年 1 月 2 日 2
01/01/2001 2
01/01/2002 1.5
2002 年 1 月 2 日 1.6
[{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"}]

我想将其转换为列:

二月
2000 1 2
2001年 2
2002年 1.5 1.6
[{Year: "2000", Jan: "1", Feb: "2"},
{Year: "2001", Jan: "", Feb: "2"},
{Year: "2002", Jan: "1.5", Feb: "1.6"}]

如何在 Angular 中使用 RxJS / TypeScript / JavaScipt 更改它?

谢谢。

4

3 回答 3

1

这需要许多步骤来完成转换。

  1. 将字符串日期转换为可用的 JavaScript 日期对象
    • 因为日期是 mm/dd/YYYY,而不是 dd/mm/YYYY,所以必须转置
    • 然后使用分解的字符串构造一个新的日期
  2. 那么这只是构造新对象的问题
  3. 其输出是每个日期与必须组合的相应值
    • 如果匹配正确,则第二个迭代器 ( .reduce()) 组合对象Year

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

const result = input.map(i => {
  const [day, month, year] = i.date.split('/');
  const [_, monthName] = new Date(year, month - 1, day).toDateString().split(' ');
  return {
    Year: year,
    [monthName]: i.value
  }
}).reduce((acc, d, idx) => {
  if (idx == 0) { 
    acc.push(d);
  } else if (acc[acc.length - 1].Year == d.Year) {
    acc[acc.length - 1] = Object.assign(acc[acc.length-1], d);
  } else {
    acc.push(d);
  }
  return acc;
}, []);

console.log(result);

于 2021-02-22T18:57:18.470 回答
1

请参阅下面使用reduce的方法

const initial = [{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"}]

const allMonths = initial.reduce((prev, next) => {
  const date = next.date.substr(6,4) + '/' + next.date.substr(3,2)
  const month =  new Date(date).toLocaleString('default', { month: 'short' });
  return {...prev, [month]: ''}
}, {})

const temp = initial.reduce(
  (prev, next) => {
    const date = next.date.substr(6,4) + '/' + next.date.substr(3,2)
    const month =  new Date(date).toLocaleString('default', { month: 'short' });
    
    const Year = new Date(date).getFullYear()
    let prevYearVal = prev[Year]
    if(!prevYearVal) { prevYearVal = {Year,...allMonths} ;}
    return {...prev, [Year]: {...prevYearVal,Year, [month]: next.value}}
    
    return prev
  },
  {}
)
const final = Object.values(temp)
console.log(final)

于 2021-02-22T18:58:58.003 回答
1

这是一个与 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}
  }), {})
)

它的工作方式相同,效率稍低,但我觉得它更干净。

于 2021-02-23T14:30:01.063 回答