Given an array of objects, how do I sort objects by depth of property n

I have an array of objects that I want to sort by some data from grouping properties, and a line telling me which property to group (for example: "Organization" or "Organization .Name")

I need to write a function that takes data that looks like beforeData and returns afterData

Entrance:

 beforeData = [ {'name':'John Doe', 'Id':1, 'Organizations':[{'Id':12, 'LongName': 'Group A'},{'Id':13, 'LongName': 'Group B'}]}, {'name':'FooBar', 'Id':2, 'Organizations':[{'Id':13, 'LongName': 'Group B'},{'Id':14, 'LongName': 'Group C'}]}, {'name':'Kristine Bell', 'Id':3, 'Organizations':[{'Id':12, 'LongName': 'Group A'}]}, {'name':'Adrian P', 'Id':4, 'Organizations':[{'Id':12, 'LongName': 'Group A'}]} ] 

Output:

  afterData = [ { 'Group': 'Group A', 'entities':[ {'name':'Adrian P', 'Id':4, 'Organizations':[{'Id':12, 'LongName': 'Group A'}]}, {'name':'Kristine Bell', 'Id':3, 'Organizations':[{'Id':12, 'LongName': 'Group A'}]}, {'name':'John Doe', 'Id':1, 'Organizations':[{'Id':12, 'LongName': 'Group A'},{'Id':13, 'LongName': 'Group B'}]}] }, { 'Group': 'Group B', 'entities':[ {'name':'John Doe', 'Id':1, 'Organizations':[{'Id':12, 'LongName': 'Group A'},{'Id':13, 'LongName': 'Group B'}]}, {'name':'FooBar', 'Id':2, 'Organizations':[{'Id':13, 'LongName': 'Group B'},{'Id':13, 'LongName': 'Group C'}]},] }, { 'Group': 'Group C', 'entities':[ {'name':'FooBar', 'Id':2, 'Organizations':[{'Id':13, 'LongName': 'Group B'},{'Id':13, 'LongName': 'Group C'}]},] } ] 

How can i do this? My current attempts are extremely bloated and forever require large datasets.

Special kicker! : A function that solves this problem should be able to solve it without knowing in advance whether the "group by property" is 1 or 2 deep (for example: "Organization" or 'Organization.LongName').

+6
source share
1 answer

Something from me:

 // this function performs data extraction from an object // the first argument is a name of the property to be extracted // it might be just a 1st level deep value like `name` // or nested like `foo.bar.baz` // in case if one of intermediate items is an array - an array of // results is returned function dot(name, obj) { if (!name) { return obj; } var match = name.match(/^([^.]+)(?:\.(.*))?$/), head = match[1], tail = match[2]; if (Array.isArray(obj)) { return obj.map(function(item) { return dot(name, item); }); } if (obj === null || typeof obj != 'object') { return null; } return dot(tail, obj[head]); } // this function accepts an array of data and a key to group by // as a result it returns an object with keys equal to a group by key // and values that hold that key function groupBy(data, key) { return data.reduce(function(result, item) { var keys = dot(key, item); if (!Array.isArray(keys)) { keys = [keys]; } keys.forEach(function(key) { if (!(key in result)) { result[key] = []; } result[key].push(item); }); return result; }, {}); } console.log(groupBy(beforeData, 'Organizations.LongName')); 

JSFiddle: http://jsfiddle.net/w8N4j/

Now it can be easily reformatted to any other format you want.

For example, to get the exact format from the question, here is a tiny transformer:

 function transformerExample(hash) { var result = []; for (var key in hash) if (hash.hasOwnProperty(key)) { result.push({ Group: key, entities: hash[key] }); } return result; } 

PS: the main implementation, obviously, may not handle all possible errors. Depending on the actual requirements, it is not difficult to improve it.

+4
source

Source: https://habr.com/ru/post/971406/


All Articles