How to sort a nested array using lodash - javascript

I have a collection of objects in this array and I need to order them by the 'order' key (asc). Is there a way to sort the objects inside the array and then return the whole array? I am relying on the order as I'm using it in a v-for with a :key.
[
{
"id":0,
"type":"Header",
"order":1,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":0,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
],
[
//Another collection of objects
]
I am currently doing this -
getters: {
sorted: state => {
return _.orderBy(state.experience_sections, function(block) {
if(block.experience_blocks[0]) {
return block.experience_blocks[0].order;
}
});
}
}
The solution above does not seem to order the objects by 'asc' order. Am I on the right track?
Thanks!
P.S. Stack is telling me that is a possible duplicate question but I'm at a loss after hours of searching. My apologies if I missed an already answered question.

Just in case you want plain javascript solution.. using Array.forEach
I have also extended your array to contain more data
var arr = [[
{
"id":0,
"type":"Header",
"order":1,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":0,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
], [
{
"id":0,
"type":"Header",
"order":2,
"props":{
"order":0,
"id":0,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
},
{
"id":1,
"type":"Header",
"order":1,
"props":{
"order":1,
"id":1,
"section_id":0
},
"data":{
"header":""
},
"component":"header-block"
}
]]
arr.forEach(d => d.sort((a,b) => a.order - b.order))
console.log(arr)

You should also consider orderBy method from lodash since you could easily change from asc to desc sort order if you would want to at a later date or have it via a variable being passed through the UI etc:
const data = [ [{ "id": 0, "type": "Header", "order": 1, "props": { "order": 0, "id": 0, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" }, { "id": 1, "type": "Header", "order": 0, "props": { "order": 1, "id": 1, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" } ], [{ "id": 0, "type": "Header", "order": 2, "props": { "order": 0, "id": 0, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" }, { "id": 1, "type": "Header", "order": 1, "props": { "order": 1, "id": 1, "section_id": 0 }, "data": { "header": "" }, "component": "header-block" } ] ]
console.log('asc:', _.map(data, x => _.orderBy(x, 'order'))) // asc order
console.log('desc:', _.map(data, x => _.orderBy(x, 'order', 'desc'))) // desc
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Will sort each subarray in an array
const sortedArr = _.map(arr, subArray => _.sortBy(subArray, "order"));

Deep sorting using lodash
const sortedArray = _.orderBy(items, [(item) => {
const nestedObj = _.get(item, 'props');
item['props'] = _.orderBy(nestedObj,'order','desc');
return item['order'];
}], 'desc');

Related

javascript print nested array to screen

I have a data array, there are multiple objects in this array, and the data object is an array. There may be more than one object in this array. How can I copy these objects under a single array?
const test = []
const data = [
{
"_id": "124141",
"name": "test",
"data": [
{
"price":10,
"title": "sda"
},
]
},
{
"_id": "2525",
"name": "test2",
"data": [
{
"price":20,
"title": "asdas"
},
]
}
]
[{
"price":10,
"title": "sda"
},
{
"price":20,
"title": "asdas"
},
]
If this is the output I expect, it should be like this. how can I do that
const data = [
{
"_id": "124141",
"name": "test",
"data": [
{
"price":10,
"title": "sda"
},
{
"price":99,
"title":"aaaaa"
}
]
},
{
"_id": "2525",
"name": "test2",
"data": [
{
"price":20,
"title": "asdas"
},
]
}
];
console.log(data.map(e => e.data).flat());
// OR
console.log(data.flatMap(e => e.data));

how to sort array of object in js by property i.ecategoryname' in my dataset in alphabetical order using mergesort

Here is the list of data that should be sorted in alphabetical based of categoryName
value using merger sort
const filteritem = [
{
"categoryName": "admission",
"rows": [
{
"uploaddate": "8/8/2022",
"title": "binoddocs",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"fullname": "bruno",
"id": "B8QsXYVFH8fHt3PrBYUp"
}
]
},
{
"categoryName": "officialdocument",
"rows":
{
"file": null,
"uploadedby": "bruno",
"uploaddate": "6/27/2022",
"title": "sudhikchaadmission",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"id": "Z27GLizWnYTJvLQyYRQt"
},
{
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"uploadedby":"bruno",
"uploaddate":"6/27/2022",
"title":"ankitadmission",
"file":null,
"id":"rmcbUrg9TpFhQh5RLqva"
}
]
},
{
"categoryName":"syallabus",
"rows": [
{
"fullname":"bruno",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"title":"sudhir",
"uploaddate":"8/15/2022",
"id":"hi7QEOlBzzVLZ1QHYqlk"
}
]
},
{
"categoryName":"Binodkhatricv",
"rows": [
{
"title":"binodtry",
"fullname":"bruno",
"uploaddate":"8/15/2022",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"id":"o4EtP1xkbWMk1icp4uNH"
}
]
i can use filter and includes method to sort.. but i have to implement some types of algorithm in my project like{mergersort ,bubblesort,depthsearch etc}but for now i need to use mergesort***
The final result should be like this i have not included all the property inside the object here i think you got it ..
filteritem=[
{categoryName:"admission"...},
{cateogryName:"Binodkhatricv"..},
{categoryName:"officialdocument"...},
{categoryName:"syallabus"...}
]```
You can use sort I guess it's do want to try to do :
const filteritem = [
{
"categoryName": "admission",
"rows": [
{
"uploaddate": "8/8/2022",
"title": "binoddocs",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"fullname": "bruno",
"id": "B8QsXYVFH8fHt3PrBYUp"
}
]
},
{
"categoryName": "officialdocument",
"rows":
[{
"file": null,
"uploadedby": "bruno",
"uploaddate": "6/27/2022",
"title": "sudhikchaadmission",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"id": "Z27GLizWnYTJvLQyYRQt"
},
{
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"uploadedby":"bruno",
"uploaddate":"6/27/2022",
"title":"ankitadmission",
"file":null,
"id":"rmcbUrg9TpFhQh5RLqva"
}
]
},
{
"categoryName":"syallabus",
"rows": [
{
"fullname":"bruno",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"title":"sudhir",
"uploaddate":"8/15/2022",
"id":"hi7QEOlBzzVLZ1QHYqlk"
}
]
},
{
"categoryName":"Binodkhatricv",
"rows": [
{
"title":"binodtry",
"fullname":"bruno",
"uploaddate":"8/15/2022",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"id":"o4EtP1xkbWMk1icp4uNH"
}
]
}];
let sorted = filteritem.sort((a, b) => (a < b ? -1 : 1))
console.log(sorted)
You need to use localeCompare to sort the string, but after toLowerCase to ignore case sensitivity.
const filteritem = [
{
"categoryName": "admission",
"rows": [
{
"uploaddate": "8/8/2022",
"title": "binoddocs",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"fullname": "bruno",
"id": "B8QsXYVFH8fHt3PrBYUp"
}
]
},
{
"categoryName": "officialdocument",
"rows": [
{
"file": null,
"uploadedby": "bruno",
"uploaddate": "6/27/2022",
"title": "sudhikchaadmission",
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"id": "Z27GLizWnYTJvLQyYRQt"
},
{
"view": "https://firebasestorage.googleapis.com/v0/b/auth",
"uploadedby":"bruno",
"uploaddate":"6/27/2022",
"title":"ankitadmission",
"file":null,
"id":"rmcbUrg9TpFhQh5RLqva"
}
]
},
{
"categoryName":"syallabus",
"rows": [
{
"fullname":"bruno",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"title":"sudhir",
"uploaddate":"8/15/2022",
"id":"hi7QEOlBzzVLZ1QHYqlk"
}
]
},
{
"categoryName":"Binodkhatricv",
"rows": [
{
"title":"binodtry",
"fullname":"bruno",
"uploaddate":"8/15/2022",
"view":"https://firebasestorage.googleapis.com/v0/b/auth",
"id":"o4EtP1xkbWMk1icp4uNH"
}
]
}
]
const result = filteritem.sort((a, b) => a.categoryName.toLowerCase().localeCompare(b.categoryName.toLowerCase()))
console.log(result)

How to combine 2 nested array of object values

How do I combine 2 nested arrays.
There are 2 Array A and B
const A = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
}
]
.
const B = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
.
on combining A and B the output should be of below format.
We need to take risk from table A and we need to take master from table B and add it to table C.
The Final array looks like the following.
.
const c = [
{
"id": 0,
"bp": true,
"ba": "value1",
"risk": [
{
"id": 0.1,
"rk": false,
"title": "risk1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
},
{
"id": 0.13,
"ctl": "ctl2"
}
]
},
{
"id": 0.1223,
"rk": false,
"title": "risk23"
}
],
"master": [
{
"id": 0.2,
"mk": false,
"title": "obli1",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
},
{
"id": 0.211,
"mk": true,
"title": "obli44",
"control": [
{
"id": 0.12,
"ctl": "ctl1"
}
]
}
]
},
{
"id": 2,
"bp": true,
"ba": "value2"
},
{
"id": 3,
"bp": true,
"ba": "value3"
}
]
The data can be more than 1000 records. please help me with which it will save time and complexity.
Thanks in Advance.
The first thing you need to do is to isolate the IDs from array A and B. You can also map over the two of them concatenated together, but then you may have duplicate values. This seems like a rational way to go about ensuring single entries for each ID.
const allIds = [...a.map(x => x.id), ...b.map(x => x.id)];
const uniqueIds = allIds.reduce((prev, curr) => {
return prev.includes(curr) ? prev : [...prev, curr]
}, []);
Then you need to take those uniqueIds, and map over each of them. For each ID, you need to return the matching object in A and the matching object in B, but overwrite the risk property with the value from the object in A and overwrite the master property with the value from the object in B.
That can be done by just finding the matching objects in A and B, and then use the spread operator to assign their entries to the new object.
Note: If the properties outside of risk and master (e.g. bp or ba) have different values, then the element listed last will overwrite it. In the below case, that means if the bp value in A is true and the bp value in B is false, then the bp value in C will be false.
const c = uniqueIds.map(id => {
const elementInA = a.find(x => x.id === id);
const elementInB = b.find(x => x.id === id);
return {
...elementInA,
...elementInB,
risk: [
...elementInA?.risk ?? []
],
master: [
...elementInB?.master ?? []
]
};
});
Instead of looping through multiple times both arrays, I would suggest something that will loop through each array, not more than needed.
The following approach will loop through twice the first array, and once the B array. (not considering the indexOf method).
const ids = A.map(({id}) => id), C = A.map(a => a);
for(let b of B){
let index = ids.indexOf(b.id);
if(index < 0){
C.push(b);
} else {
C[index] = {
...A[index],
...b,
risk: [
...A[index]?.risk ?? []
],
master: [
...b?.master ?? []
]
}
}
}

How to groupBy in multi arrays using lodash

I want to group By sub-work in array
Here is my array I want to group By sub-work
result = [
{
"date": "10-07-2019",
"data": [
{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [
{
"id": 7,
"title": 'subdata-1',
}
]
}
]
},
{
"date": "12-07-2019",
"data": [
{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [
{
"id": 7,
"title": 'subdata-1',
}
]
}
]
},
]
Here is what I try
result = _(result)
.map(function(items, data) {
_.groupBy(items.data, function({ sub_work }) {
return sub_work;
});
})
.value();
first I map result into data then I try to groupby but It's return null
Update
I want my output look like this
[
{
"date": "10-07-2019",
sub-work: [{
sub-work : "sub_work1",
sub-data[
{
"id": 7,
"title": 'subdata-1',
}
]
}]
}
]
...........................
It would be better if you could provide your expected result.
Here's what I could infer:
_(result)
.map(function(obj) { // Convert into a 2D array.
return obj.data.map(e => Object.assign(e, {date: obj.date}));
})
.flatten() // We have an array of objects now.
.groupBy('sub-work') // We can call groupBy().
.value();
Here's what you get:
{
"sub_work1": [{
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [{
"id": 7,
"title": "subdata-1"
}],
"date": "10-07-2019"
}, {
"data_id": "20",
"work": "work_1",
"sub-work": "sub_work1",
"sub-data": [{
"id": 7,
"title": "subdata-1"
}],
"date": "12-07-2019"
}]
}

Parse a nested array objects, and create a new array

I have a nested array of objects that I am parsing in JavaScript, but I'm having difficulty creating the target array.
Here's the properly-rendered Kendo UI treeview with a sample array attached to it (i.e. the way the final dataSource array should look like):
http://plnkr.co/edit/YpuXJyWgGI7h1bWR0g70?p=preview
Kendo UI treeview widget
My source array has nested "children" arrays, where the leaf node is the "drms" array.
As I parse the nested children, I am trying to do the following :
the non-empty "children" array needs to be renamed to "drms"
the empty "children" array needs to be deleted
Here is a sample source array:
[ /* SOURCE ARRAY */
{
"category": "Market Risk",
"sysid": 1,
"children": [
{
"category": "General",
"sysid": 2,
"children": [],
"drms": [
{
"name": "1 Day VaR (99%)"
},
{
"name": "10 Day VaR (99%)"
}
]
},
{
"category": "Decomposition",
"sysid": 3,
"children": [],
"drms": [
{
"name": "1D VaR Credit"
},
{
"name": "1D VaR Equity"
}
]
},
{
"category": "Sensitivities",
"sysid": 4,
"children": [
{
"category": "Currency Pairs",
"sysid": 11,
"children": [
{
"category": "EUR/USD",
"sysid": 12,
"children": [],
"drms": [
{
"name": "Spot"
},
{
"name": "Spot - 0.01"
}
]
}
],
"drms": []
}
],
"drms": []
}
],
"drms": []
},
{
"category": "CCR",
"sysid": 6,
"children": [
{
"category": "General (CCR)",
"sysid": 7,
"children": [],
"drms": [
{
"name": "MTM"
},
{
"name": "PFE"
}
]
}
],
"drms": []
}
]
and the target array which I've modified manually in order to render the Kendo TreeView :
[
{
"category": "Market Risk",
"sysid": 1,
"drms": [
{
"category": "General",
"sysid": 2,
"drms": [
{
"name": "1 Day VaR (99%)",
"riskMeasure": "-PERCENTILE(SUM([99_HSVaR]:[1D]),1)",
"cubeVector": "[99_HSVaR]:[1D]"
},
{
"name": "10 Day VaR (99%)",
"riskMeasure": "-PERCENTILE(SUM([99_HSVaR]:[2W]),1)",
"cubeVector": "[99_HSVaR]:[2W]"
},
{
"name": "Day over Day VaR",
"riskMeasure": "-PERCENTILE(SUM(today),1)+PERCENTILE(SUM(yesterday),1)",
"cubeVector": "[BASELINE]:[99_HSVaR]:[2W] as today, [BASELINE-1]:[99_HSVaR]:[2W] as yesterday"
}
]
},
{
"category": "Decomposition",
"sysid": 3,
"drms": [
{
"name": "1D VaR Credit",
"riskMeasure": "SUM([99_HSVaR]:[1D CR])",
"cubeVector": "[99_HSVaR]:[1D CR]"
},
{
"name": "1D VaR Equity",
"riskMeasure": "SUM([99_HSVaR]:[1D EQ])",
"cubeVector": "[99_HSVaR]:[1D EQ]"
}
]
},
{
"category": "Sensitivities",
"sysid": 4,
"drms": [
{
"category": "Currency Pairs",
"sysid": 11,
"drms": [
{
"category": "EUR/USD",
"sysid": 12,
"children": [],
"drms": [
{
"name": "Spot",
"riskMeasure": "SUM([EUR_USD by EUR]:[Spot - 0.00])",
"cubeVector": "[EUR_USD by EUR]:[Spot - 0.00]"
},
{
"name": "Spot - 0.01",
"riskMeasure": "SUM([EUR_USD by EUR]:[Spot - 0.01])",
"cubeVector": "[EUR_USD by EUR]:[Spot - 0.01]"
}
]
}
],
}
]
}
],
},
{
"category": "CCR",
"sysid": 6,
"drms": [
{
"category": "General (CCR)",
"sysid": 7,
"drms": [
{
"name": "MTM",
"riskMeasure": "SUM(MTM:MTM)",
"cubeVector": "MTM:MTM"
},
{
"name": "PFE",
"riskMeasure": "PERCENTILE(SUM(x),95)",
"cubeVector": "[Simulated]:[MCS] IF value > 0 as x"
}
]
}
]
}
]
and my JavaScript routine which is not quite working yet. A bit of confusion while parsing the nested children:
function create_TempDrmTree() {
// convert raw def risk measures (drm) data into a tree format for the Kendo treeview widget.
var data = getTestDrmTree();
var drmsJson = [];
var i = 0;
_.each(data, function (item) {
drmsJson.push({ "category": item.category, drms: [] });
if (item.children.length > 0) {
pushDrms(item.children);
}
i++;
});
function pushDrms(children) {
_.each(children, function (item) {
if (item.children.length > 0) {
pushDrms(item.children);
}
else {
// no more children, so get the DRMs from item
// leaving tempty children[] causes an issue on Kendo treeview
delete item.children;
drmsJson[i]["drms"] = item;
}
});
}
return drmsJson;
}
Based on your original idea, I modified it slightly. This works perfectly for my scenario.
EDITED: from What is the most efficient way to clone an object?, we can easily create a brand new array and keep original one untouched.
function parseDrmTree(items, isCloned) {
if (isCloned !== true) {
// Create json string from original item, and then parse it.
// And only do this at the root.
items = JSON.parse(JSON.stringify(items));
isCloned = true;
}
// reparse the DRM source tree, renaming "children" array to "drms".
items.forEach(function (item, index) {
if (item.children.length > 0) {
// copy children[] to drms[]
item.drms = parseDrmTree(item.children, isCloned);
}
// children[] is empty; drms[] exist at this level
delete item.children;
}, this);
return items;
}
You don't have to give an isCloned value, just input the target array, the function will create a brand new array, and use it to create the desired structure, and the origin one is untouched.

Categories

Resources