简体   繁体   中英

Group Array of objects into specific format using lodash

I have this array of objects, that I need to modify to make the rendering easier . I used some code mentioned in a similar question : Group array of object nesting some of the keys with specific names

Here's my array and code

 function groupAndMap(events, Year, Month, predic){ return _.map(_.groupBy(events,Year), (obj,key) => ({ [Year]: key, [Month]: (predic && predic(obj)) || obj })); } const items = [ { "Year": 2018, "Month": 7, "Day": 2, "Title": "event1", "StartDate": "2018-07-02T10:00:00.000Z", "EndDate": "2018-07-02T11:00:00.000Z" }, { "Year": 2018, "Month": 8, "Day": 31, "Title": "event2", "StartDate": "2018-07-31T10:00:00.000Z", "EndDate": "2018-08-02T11:00:00.000Z" } ]; function groupAndMap(items, itemKey, childKey, predic){ return _.map(_.groupBy(items,itemKey), (obj,key) => ({ [itemKey]: key, [childKey]: (predic && predic(obj)) || obj })); } var result = groupAndMap(items,"Year","Months", arr => groupAndMap(arr,"Month", "Days")); var jsonvalue = JSON.stringify(result); document.write(jsonvalue); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script> 

I want my output to be in the following format

 [{ "Year": "2019", "Months": [{ "Month": "8", "Days": [{ "Day": "31", "Events": [{ "Year": 2019, "Month": 8, "Day": 31, "Title": "event3", "StartDate": "2018-07-31T10:00:00.000Z", "EndDate": "2018-08-02T11:00:00.000Z" }] }] }] }] 

How should i modify the code in order to get this result ?

You could use an array with the keys to group for the nested objects.

 function groupAndMap(events, groups) { return _(events) .groupBy(groups[0]) .map((array, key) => ({ [groups[0]]: key, [groups[1] + 's']: groups[2] && groupAndMap(array, groups.slice(1)) || array })) .values(); } var items = [{ Year: 2018, Month: 7, Day: 2, Title: "event1", StartDate: "2018-07-02T10:00:00.000Z", EndDate: "2018-07-02T11:00:00.000Z" }, { Year: 2018, Month: 8, Day: 31, Title: "event2", StartDate: "2018-07-31T10:00:00.000Z", EndDate: "2018-08-02T11:00:00.000Z" }], result = groupAndMap(items, ["Year", "Month", "Day", "Event"]); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script> 

With defined keys for the result

 function groupAndMap(events, groups, keys) { return _(events) .groupBy(groups[0]) .map((array, key) => ({ [groups[0]]: key, [groups[1] + 's']: groups[2] && groupAndMap(array, groups.slice(1), keys) || _.map(array, o => _.pick(o, keys)) })) .values(); } var items = [{ Year: 2018, Month: 7, Day: 2, Title: "event1", StartDate: "2018-07-02T10:00:00.000Z", EndDate: "2018-07-02T11:00:00.000Z" }, { Year: 2018, Month: 8, Day: 31, Title: "event2", StartDate: "2018-07-31T10:00:00.000Z", EndDate: "2018-08-02T11:00:00.000Z" }], result = groupAndMap(items, ["Year", "Month", "Day", "Event"], ['Title', 'StartDate', 'EndDate']); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.js"></script> 

I think its the easiest if you group by an array of criterias:

const entries = Symbol.for("entries");
const tree = { [entries]: [] };
const groups = ["Year", "Month", "Day"];
const childNames = ["Months", "Days", "Events"];

for(const item of items) {
  let node = tree;
  for(const [index, group] of groups.entries()) {
    const childName = childNames[index];
    const key = item[group];
    if(node[key]) {
      node = node[key];
    } else {
      const children = [];          
      node[entries].push({
          [group]: key,
          [childName]: children
      });
      node = node[key] = { [entries]: children };
    }
  }
  node[entries].push(item);
}

const result = tree[entries];

That allows you to access an event as:

 for(const event of tree[2017][12][31][entries])

and result contains the datastructure you needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM