Format a long array of js object separating dates

2019-08-25 15:59发布

问题:

let dates = {
              '2018/07/25': [['1','red'], ['1','orange'], ['3','blue']],
              '2018/07/26': [['2','black'], ['4','orange'], ['4','pink']],
              '2018/08/01': [['3','purple'], ['4','green']]
            } 

The newObject expected is:

newObject = {
             '2018/07':{
                         '2018/07/25': {
                                         '1':['red','orange'],
                                         '3':['blue']
                                       },
                         '2018/07/26': {
                                         '2':['black'],
                                         '4':['orange','pink']
                                       }
                       },
             '2018/08':{
                         '2018/08/01': {
                                         '3':['purple'],
                                         '4':['green']
                                       }
                       }
             }

My code so far:

let newObject = {};

Object.keys(dates).forEach((onedate, index) => {
    let monthdate = onedate.slice(0,7)
    if (!newObject[monthdate]) {
        newObject[monthdate] = {};
    }    
    newObject[monthdate][onedate] = [...dates[onedate]];
});

The output of above code:

newObject = {
             "2018/07":{
                         "2018/07/25": [["1","red"],["1","orange"],["3","blue"]],
                         "2018/07/26": [["2","black"],["4","orange"],["4","pink"]]
                        },
             "2018/08":{
                         "2018/08/01": [["3","purple"],["4","green"]]
                       }
             }

I want to remove array in level 3 depth too. Also separate the first number maybe using Sets and have their respective relation to colors

"2018/07/25": [["1","red"],["1","orange"],["3","blue"]]

to

'2018/07/25': {'1':['red','orange'],'3':['blue']}

回答1:

Can use a basic reduce() on the arrays to map them to object structure you want

let dates = {
              '2018/07/25': [['1','red'], ['1','orange'], ['3','blue']],
              '2018/07/26': [['2','black'], ['4','orange'], ['4','pink']],
              '2018/08/01': [['3','purple'], ['4','green']]
            }
            
let newObject = {};

Object.keys(dates).forEach((onedate, index) => {
    let monthdate = onedate.slice(0,7)
    if (!newObject[monthdate]) {
        newObject[monthdate] = {};
    }    
    newObject[monthdate][onedate] = dates[onedate].reduce((a,c)=>{
        a[c[0]] = a[c[0]] || [];
        a[c[0]].push(c[1])
        return a;
    },{})
});

console.log(newObject)



回答2:

You're really close to find the solution. Here is how you can do it using a reducer:

let dates = {
  '2018/07/25': [['1','red'], ['1','orange'], ['3','blue']],
  '2018/07/26': [['2','black'], ['4','orange'], ['4','pink']],
  '2018/08/01': [['3','purple'], ['4','green']]
};

let newObject = {};

Object.keys(dates).forEach((onedate, index) => {
  const colors = dates[onedate];

  const colorsMap = colors.reduce((accumulator, [monthId, color]) => {
    accumulator[monthId] = accumulator[monthId] === undefined ? [] : accumulator[monthId];
    accumulator[monthId].push(color);
    return accumulator;
  }, Object.create(null));

  let monthdate = onedate.slice(0,7)
  if (!newObject[monthdate]) {
    newObject[monthdate] = {};
  }
  newObject[monthdate][onedate] = colorsMap;
});

console.log(newObject)