Reshape objects using groupby

时光总嘲笑我的痴心妄想 提交于 2021-02-10 14:58:36

问题


I have the following array of objects:

    const data=[
        {
            "datetime": "2020-01-30T00:59:59.000Z",
            "Benzene": 3.6
        },
        {
            "datetime": "2020-01-30T00:59:59.000Z",
            "O3": 3.7
        },
        {
            "datetime": "2020-01-30T00:59:59.000Z",
            "PM10": 3.1
        },
    
       {
            "datetime": "2020-03-30T00:59:59.000Z",
            "Benzene": 2.6
        },
        {
            "datetime": "2020-03-30T00:59:59.000Z",
            "O3": 5.7
        },
        {
            "datetime": "2020-03-30T00:59:59.000Z",
            "PM10": 10.5
       

 }
]

I want to reshape it by grouping by Date only as follow:

[{ "date":"2020-01-30",
   "values":[{"t":"2020-01-30T00:59:59.000Z",
              "Benzene":3.6,
              "O3":3.7,
              "PM10":3.1}]},
{ "date":"2020-03-30",
   "values":[{"t":"2020-03-30T00:59:59.000Z",
              "Benzene":2.6,
              "O3":5.7,
              "PM10":10.5}]}]

I suppose that I can accomplish this using Loadash and .map, but I can't figure it how.

Any suggestion?


回答1:


You can apply groupBy first from lodash to group elements by their datetime and then apply reduce to both map and combine values of each group elements. A possible approach could be as below

const data = [{
    "datetime": "2020-01-30T00:59:59.000Z",
    "Benzene": 3.6
  },
  {
    "datetime": "2020-01-30T00:59:59.000Z",
    "O3": 3.7
  },
  {
    "datetime": "2020-01-30T00:59:59.000Z",
    "PM10": 3.1
  },

  {
    "datetime": "2020-03-30T00:59:59.000Z",
    "Benzene": 2.6
  },
  {
    "datetime": "2020-03-30T00:59:59.000Z",
    "O3": 5.7
  },
  {
    "datetime": "2020-03-30T00:59:59.000Z",
    "PM10": 10.5
  }
];

const groups = _.groupBy(data, i => i['datetime'].substring(0, 10));

const res = Object.entries(groups).reduce((acc, g) => {
  const [key, values] = g;
  acc.push({
    date: key,
    values: [Object.assign({}, ...values)]
  });
  return acc;
}, []);
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.min.js"></script>



回答2:


To get the exact desired output, try:

const result = data.reduce((acc, val) => {
    const find = acc.find(el => el.date === val.datetime.substring(0, 10));
    const { datetime, ...obj } = val;

    if (find) {
        find.values[0] = { ...find.values[0], ...obj };
    } else {
        acc.push({ date: datetime.substring(0, 10), values: [{ t: datetime, ...obj }] });
    }

    return acc;
}, []);



回答3:


This can be done in javascript without lodash, like other answers, here is my try with reduce:

var data=[ { "datetime": "2020-01-30T00:59:59.000Z", "Benzene": 3.6 }, { "datetime": "2020-01-30T00:59:59.000Z", "O3": 3.7 }, { "datetime": "2020-01-30T00:59:59.000Z", "PM10": 3.1 }, { "datetime": "2020-03-30T00:59:59.000Z", "Benzene": 2.6 }, { "datetime": "2020-03-30T00:59:59.000Z", "O3": 5.7 }, { "datetime": "2020-03-30T00:59:59.000Z", "PM10": 10.5 }];

var result = Object.values(data.reduce((acc,{datetime, ...rest})=>{
    const date = datetime.slice(0,10)
    acc[date] = acc[date] || {date, values:[]};
    acc[date].values = [{...acc[date].values[0], ...{t:datetime, ...rest}}];
    return acc;
},{}));

console.log(result);



回答4:


You can use reduce instead

const data = [
    {
        datetime: '2020-01-30T00:59:59.000Z',
        Benzene: 3.6,
    },
    {
        datetime: '2020-01-30T00:59:59.000Z',
        O3: 3.7,
    },
    {
        datetime: '2020-01-30T00:59:59.000Z',
        PM10: 3.1,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        Benzene: 2.6,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        O3: 5.7,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        PM10: 10.5,
    },
];

const result = data.reduce((acc, val) => {
    const tryFind = acc.find(el => el.date === val.datetime);
    const { datetime, ...valExcludeDate } = val;

    if (tryFind) {
        tryFind.values[0] = { ...tryFind.values[0], ...valExcludeDate };
    } else {
        acc.push({ date: datetime, values: [{ ...valExcludeDate }] });
    }

    return acc;
}, []);

console.log(result);

but I think object as a result will suit you more

const data = [
    {
        datetime: '2020-01-30T00:59:59.000Z',
        Benzene: 3.6,
    },
    {
        datetime: '2020-01-30T00:59:59.000Z',
        O3: 3.7,
    },
    {
        datetime: '2020-01-30T00:59:59.000Z',
        PM10: 3.1,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        Benzene: 2.6,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        O3: 5.7,
    },
    {
        datetime: '2020-03-30T00:59:59.000Z',
        PM10: 10.5,
    },
];

const result = data.reduce((acc, val) => {
    const { datetime, ...valExcludeDate } = val;

    if (acc[val.datetime]) {
        acc[val.datetime] = { ...acc[val.datetime], ...valExcludeDate };
    } else {
        acc[val.datetime] = { ...valExcludeDate };
    }

    return acc;
}, {});

console.log(result);


来源:https://stackoverflow.com/questions/62510189/reshape-objects-using-groupby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!