4

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 ?

2 Answers 2

1

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>

Sign up to request clarification or add additional context in comments.

1 Comment

Do you have any idea on how can i omit Year ,Month and Day keys from the Events array ? @NinaScholz
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.