Sort a flat list by parent id with lodash - javascript

I have a JSON list of objects with an id, name and reference to parent id :
const myList = [
{
id: 1,
name: "name1",
parentId: null
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 48,
name: "name48",
parentId: 1
}
]
I would like to sort that list hierarchically, depending on the parent id :
[
{
id: 1,
name: "name1",
parentId: null
},
{
id: 48,
name: "name48",
parentId: 1
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 5,
name: "name5",
parentId: 32
}
]
I'm new in Javascript programming and lodash, and I was wondering if there is an easy way to sort that list with lodash ?
Thank you in advance.
Benj

I found a solution with lodash.
Not sure it's the best but it works.
var parentId = null;
var sortedList = [];
var byParentsIdsList = _.groupBy(myList, "parentId"); // Create a new array with objects indexed by parentId
while (byParentsIdsList[parentId]) {
sortedList.push(byParentsIdsList[parentId][0]);
parentId = byParentsIdsList[parentId][0].id;
}

You can use lodash's method sortBy
var sorted = _.sortBy(myList, "parentId");
console.log(sorted);
/* OUTPUT
[
{
id: 1,
name: "name1",
parentId: null
},
{
id: 48,
name: "name48",
parentId: 1
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
}
]
*/
https://jsfiddle.net/L88t09ne/

with vanilla js [].sort() method:
const myList = [
{
id: 1,
name: "name1",
parentId: null
},
{
id: 5,
name: "name5",
parentId: 32
},
{
id: 32,
name: "name32",
parentId: 48
},
{
id: 48,
name: "name48",
parentId: 1
}
];
var arr = myList.sort(function(a,b){
return a.parentId -b.parentId
});
console.log(arr)

Related

search an item in multidimentionnal array

I'm trying to find an element on a multidimentionnal array usin JAVASCRIPT function, but I get error
This is my array's data:
export const datas = [
{
id: 1,
firstName: 'John',
tables: [
{ ID: 11, title: 'Lorem' },
{ ID: 12, title: 'Ipsum' },
],
},
{
id: 2,
firstName: 'Doe',
tables: [
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
{ ID: 23, title: 'Korem' },
],
},
{
id: 3,
firstName: 'Brad',
tables: [
{
ID: 30,
title: 'Mern',
nodes: [{ name: 'Name4' }, { name: 'Name5' }, { name: 'Name6' }],
},
{
ID: 31,
title: 'Full',
nodes: [{ name: 'Name7' }, { name: 'Name8' }, { name: 'Name9' }],
},
],
},
];
I've tried a reccursive function but it's not work, this is my code :
export const findById = (arr, id) => {
for (let o of arr) {
if (o.tables.length > 0) {
let a = findById(o.tables.nodes, 'id');
console.log(a);
}
}
};
I want to print the Object with ID 22, the problem is that I don't have the same structure in each dimension, and it still confuse me..
My Input : 22
My output :
{
ID: 22,
title: 'Arke',
nodes: [{ name: 'Name1' }, { name: 'Name2' }, { name: 'Name3' }],
},
Have you an idea how to edit my function to get my input's response ?
Your recursive function wasn't too far off, you need to check if the item as a tables first before recursively calling it again. And then finally just check the ID in the loop.
eg..
const datas=[{id:1,firstName:"John",tables:[{ID:11,title:"Lorem"},{ID:12,title:"Ipsum"}]},{id:2,firstName:"Doe",tables:[{ID:22,title:"Arke",nodes:[{name:"Name1"},{name:"Name2"},{name:"Name3"}]},{ID:23,title:"Korem"}]},{id:3,firstName:"Brad",tables:[{ID:30,title:"Mern",nodes:[{name:"Name4"},{name:"Name5"},{name:"Name6"}]},{ID:31,title:"Full",nodes:[{name:"Name7"},{name:"Name8"},{name:"Name9"}]}]}];
function findById(arr, ID) {
for (const a of arr) {
if (a.tables) {
const r = findById(a.tables, ID);
if (r) return r;
}
if (a.ID === ID) return a;
}
}
console.log(findById(datas, 22));
if you just need the nested data you can use flatMap and find
const findById = (arr, id) =>
arr
.flatMap(d => d.tables)
.find(t => t.ID === id)
const datas = [{
id: 1,
firstName: 'John',
tables: [{
ID: 11,
title: 'Lorem'
},
{
ID: 12,
title: 'Ipsum'
},
],
},
{
id: 2,
firstName: 'Doe',
tables: [{
ID: 22,
title: 'Arke',
nodes: [{
name: 'Name1'
}, {
name: 'Name2'
}, {
name: 'Name3'
}],
},
{
ID: 23,
title: 'Korem'
},
],
},
{
id: 3,
firstName: 'Brad',
tables: [{
ID: 30,
title: 'Mern',
nodes: [{
name: 'Name4'
}, {
name: 'Name5'
}, {
name: 'Name6'
}],
},
{
ID: 31,
title: 'Full',
nodes: [{
name: 'Name7'
}, {
name: 'Name8'
}, {
name: 'Name9'
}],
},
],
},
];
console.log(findById(datas, 22))
js has amazing array options https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
the ones which will help you most are probably:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap
here are some examples
// get the base with id 22
const baseWith22ID = datas.filter(f => f.tables.filter(s => s.id = 22))
// (i guess you want this one) get all elements with id 22
const onlyElementsWith22ID = datas.flatMap(f => f.tables.filter(s => s.id = 22))

How to get list of parents id in json object

My nested json array looks like:
[
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
]
Now I get a id like "11"
then get the parent ids array in json like [6,9,11]
How to do?
var id = 11
console.log(findParent(id))
//result is [6,9,11]
You need to do recursive search
const persons = [
{
id: 1,
name: "Mike",
children: [
{ id: 2, name: "MikeC1" },
{ id: 3, name: "MikeC2" },
{
id: 4, name: "MikeC3",
children: [{ id: 5, name: "MikeCC1" }]
},
]
},
{
id: 6,
name: "Json",
children: [
{ id: 7, name: "JsonC1" },
{ id: 8, name: "JsonC2" },
{
id: 9, name: "JsonC3",
children: [{ id: 10, name: "JsonCC1" },{ id: 11, name: "JsonCC2" }]
},
]
}
];
function searchRecursive(items, id) {
const allIds = [];
items.forEach(item => {
if(item.id === id) {
allIds.push(item.id);
}
else if(item.children) {
const ids = searchRecursive(item.children, id);
if(ids.length) allIds.push(item.id);
ids.forEach(id => allIds.push(id));
}
});
return allIds;
}
console.log(searchRecursive(persons, 11));

How to flatten the nested Array?

How do I flatten the nested Array in the Array?
Here is the example input Array,
const input = [
{
id: 1,
name: 'Charles',
otherFields: [{
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}]
}, {
id: 4,
name: 'Charles',
otherFields: [{
id: 5,
name: 'Pung',
}, {
id: 6,
name: 'James',
}]
}
]
Output Array I want to get.
[{
id: 1,
name: 'Charles'
}, {
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}, {
id: 4,
name: 'Charles'
}, {
id: 5,
name: 'Pung',
}, {
id: 6,
name: 'James',
}]
I want to somehow get the output in one statement like
input.map((sth) => ({...sth??, sth.field...})); // I'm not sure :(
With flatMap you can take out the otherFields property, and returning an array containing the parent item and the other array:
const input = [{
id: 1,
name: 'Charles',
otherFields: [{
id: 2,
name: 'Pung',
}, {
id: 3,
name: 'James',
}]
}];
console.log(
input.flatMap(({ otherFields, ...item }) => [item, ...otherFields])
);
For more than one level, you could take a recursive approach of flattening.
const
flat = ({ otherFields = [], ...o }) => [o, ...otherFields.flatMap(flat)],
input = [{ id: 1, name: 'Charles', otherFields: [{ id: 2, name: 'Pung' }, { id: 3, name: 'James', otherFields: [{ id: 4, name: 'Jane' }] }] }],
result = input.flatMap(flat);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to add object element in array based on condition

I have static array constant of objects something similar to below.
export const EMPLOYEES = [
{
id: 2,
name: ‘John’,
},
{
id: 3,
name: ‘Doe’,
},
{
id: 4,
name: ‘Bull’,
},
{
id: 5,
name: ‘Scott’,
},
];
Now I need to add the last element only based on if some condition is true. Some this like if isAmerican() is true.
Can somebody help me here how to add element based on the condition? Thanks.
You can do it using spread operator:
export const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "Jemmy"}] : []
];
You should never modify (or try to modify) a constant. I can see two ways you can do this:
Create a pure function to return a new constant with the new object added to the array
Use a spread operator in the definition of the constant
Option 1: Pure function
function makeNewArray(array, objectToAppend, isAmerican) {
return isAmerican ? [...array, objectToAppend] : array
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
}
];
const arrayWithAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "American Frank"}, true);
const arrayWithoutAmerican = makeNewArray(EMPLOYEES, { id: 6, name: "Not American Frank"}, false);
console.log(arrayWithAmerican);
console.log(arrayWithoutAmerican);
Option 2: Spread operator
function isAmerican(){
// generic code here.
return true;
}
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
... isAmerican() ? [{ id: 6, name: "American Frank"}] : []
];
If the condition will be fulfilled, simply push an object to your EMPLOYEES array:
let isAmerican = true;
const EMPLOYEES = [
{
id: 2,
name: "John",
},
{
id: 3,
name: "Doe",
},
{
id: 4,
name: "Bull",
},
{
id: 5,
name: "Scott",
},
];
if(isAmerican) {
EMPLOYEES.push({
id: 6,
name: "Frank"
})
}
console.log(EMPLOYEES)
Fiddle: https://jsfiddle.net/rqx35pLz/

Expand/Collapse all the gof kendoTreeList

I am using kendoTreeList
and I am trying to expand all the groups. Here is my code sample
But it seems like the kendoTreeList support only expanding the first group. I tried the following selector in the expand method as well.
treeList.expand($(".k-treelist-group")); to expand all the groups. Even though the selector $(".k-treelist-group").length is 3 (total number of groups) but the treelist only expand the first group.
Any suggestion please let me know.
You are right, according with the information on their site it expands the row and not the rows.
Then you can iterate for getting the same effect:
var treeList = $("#treeList").data("kendoTreeList");
var rows = $("tr.k-treelist-group", treeList.tbody);
$.each(rows, function(idx, row) {
treeList.expand(row);
});
$(document).ready(function() {
$("#treeList").kendoTreeList({
columns: [ "id", "name" ],
loadOnDemand:false,
dataSource: [
{ id: 1, parentId: null, name: "Group", age: 30 },
{ id: 2, parentId: 1, name: "John Doe", age: 33 },
{ id: 3, parentId: 1, name: "Johson", age: 33 },
{ id: 4, parentId: null, name: "Group 2", age: 30 },
{ id: 5, parentId: 4, name: "Doe ", age: 33 },
{ id: 6, parentId: 4, name: "Noomi", age: 33 },
{ id: 7, parentId: null, name: "Group 3", age: 30 },
{ id:8, parentId: 7, name: "Doe ", age: 33 },
{ id: 9, parentId: 7, name: "Noomi", age: 33 }
]
});
var treeList = $("#treeList").data("kendoTreeList");
var rows = $("tr.k-treelist-group", treeList.tbody);
$.each(rows, function(idx, row) {
treeList.expand(row);
});
});
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2014.3.1119/styles/kendo.default.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.3.1119/js/kendo.all.min.js"></script>
<div id="treeList"></div>
If you expand many rows you can get into some performance issues, then one alternative to looping the .expand method is to modify the data and bind it again.
var treeList = $("#treeList").data("kendoTreeList");
var dataItems = treeList.dataSource.data();
$.each(dataItems, function(i, item) {
item.expanded = true;
});
treeList.dataSource.data(dataItems);
You can also modify the data before it's bound.
dataSource: {
data: [
{ id: 1, parentId: null, name: "Group", age: 30 },
{ id: 2, parentId: 1, name: "John Doe", age: 33 },
{ id: 3, parentId: 1, name: "Johson", age: 33 },
{ id: 4, parentId: null, name: "Group 2", age: 30 },
{ id: 5, parentId: 4, name: "Doe ", age: 33 },
{ id: 6, parentId: 4, name: "Noomi", age: 33 },
{ id: 7, parentId: null, name: "Group 3", age: 30 },
{ id:8, parentId: 7, name: "Doe ", age: 33 },
{ id: 9, parentId: 7, name: "Noomi", age: 33 }
],
schema: {
parse: function(data) {
$.each(data, function(i, item) {
item.expanded = true;
});
return data;
}
}
}

Categories

Resources