8

我觉得我接近答案,但我没有输出我正在寻找的格式

所以,我有这个对象数组:

const data = [
{email: '100@email.com', amount: '30', date: '2018-12'},
{email: '100@email.com', amount: '30', date: '2018-11'},
{email: '100@email.com', amount: '30', date: '2018-10'},

{email: '200@email.com', amount: 0,    date: '2018-12'},
{email: '200@email.com', amount:'30',  date: '2018-11'},
{email: '200@email.com', amount:'30',  date: '2018-10'},
{email: '200@email.com', amount:'30',  date: '2018-09'},
{email: '200@email.com', amount:'25',  date: '2018-08'},
{email: '200@email.com', amount:'25',  date: '2018-08'},]

正如您在数据集中看到的那样,有重复的电子邮件以及重复的对象,例如数据集中的最后 2 个。

我想把它变成这个对象数组:

const data = [
{
    email: '100@email.com',
    '2018-12': '30',
    '2018-11': '30',
    '2018-10': '30', 
    '2018-09': 0, 
    '2018-08': 0, 
    '2018-07': 0, 
    '2018-06': 0, 
    '2018-05': 0, 
    '2018-04': 0, 
    '2018-03': 0, 
    '2018-02': 0, 
    '2018-01': 0, 
    '2017-12': 0, 
},
{
    email: '200@email.com',
    '2018-12':0,
    '2018-11':'30',
    '2018-10':'30',
    '2018-09':'30',
    '2018-08':'25',
    '2018-07': 0,
    '2018-06': 0,
    '2018-05': 0,
    '2018-04': 0,
    '2018-03': 0,
    '2018-02': 0,
    '2018-01': 0,
    '2017-12': 0,
}]

输出的日期范围从 2017-12 到 2018-12,日期键的值是该特定日期的金额,否则如果在对象上找不到该日期,则该日期的值默认为 0

目前我正在使用类似这样的方法使用 reduce() 函数:

let result = data.reduce((acc, {email, date, amount}) => {
    acc.email = email
    acc[date] = amount
    return acc;
}, {});

结果只返回最后一封电子邮件,不完全是我正在寻找的日期范围。

在此先感谢您的帮助。

4

2 回答 2

10

归约为由 each 索引的对象,如果累加器上尚不存在email该属性,则显式创建内部对象。[email]一旦确定对象存在,就可以分配给acc[email][date],最后使用Object.values将对象转换回所需的数组格式:

const data = [
{email: '100@email.com', amount: '30', date: '2018-12'},
{email: '100@email.com', amount: '30', date: '2018-11'},
{email: '100@email.com', amount: '30', date: '2018-10'},

{email: '200@email.com', amount: 0,    date: '2018-12'},
{email: '200@email.com', amount:'30',  date: '2018-11'},
{email: '200@email.com', amount:'30',  date: '2018-10'},
{email: '200@email.com', amount:'30',  date: '2018-09'},
{email: '200@email.com', amount:'25',  date: '2018-08'},
{email: '200@email.com', amount:'25',  date: '2018-08'},]

let result = data.reduce((acc, {email, date, amount}) => {
  if (!acc[email]) acc[email] = { email };
  acc[email][date] = amount;
  return acc;
}, {});
console.log(Object.values(result));

于 2018-12-31T00:50:39.143 回答
1

const data = [
  {email: '100@email.com', amount: '30', date: '2018-12'},
  {email: '100@email.com', amount: '30', date: '2018-11'},
  {email: '100@email.com', amount: '30', date: '2018-10'},
  {email: '200@email.com', amount: 0,    date: '2018-12'},
  {email: '200@email.com', amount:'30',  date: '2018-11'},
  {email: '200@email.com', amount:'30',  date: '2018-10'},
  {email: '200@email.com', amount:'30',  date: '2018-09'},
  {email: '200@email.com', amount:'25',  date: '2018-08'},
  {email: '200@email.com', amount:'25',  date: '2018-08'},
];

/*
  Reduce into an object with email as key and email 
  and date/amount(s) as value, wrapped in Object.values 
  to return the array of augmented data values.
*/
augmentData = (data) => Object.values(
  data.reduce((acc, {email, amount, date}) => {
    (acc[email] || (acc[email] = {email}))[date] = amount;
    return acc;
  }, {})
);

/*
  Reduce straight to array of augmented data 
  objects containing email and date/amount values.
*/
augmentData2 = data => data.reduce((acc, {email, amount, date}) => {
  const findEl = (arr) => arr.find(el => el.email == email);
  const createEl = (arr, email) => arr.push({email}) && findEl(arr);
  
  (findEl(acc) || createEl(acc, email))[date] = amount;
  return acc;
}, []);

const augmentedData = augmentData(data);
console.log('augmentedData', augmentedData);

const augmentedData2 = augmentData2(data);
console.log('augmentedData2', augmentedData2);

于 2018-12-31T06:33:55.557 回答