I have an array of object that defines file and directory structure. It will vary according to reality, which may be more complicated.
Here is an example :
For example this root folder contains "folder_id": "F1" and "folder_id": "F2", and it will continue to divide ...
const folders = [
{
folder_id: "F1",
name: "Test Folder 1",
files: [
{
file_id: "File1",
name: "Whiteboard-Jun 3rd 2020, 4:56 pm"
}
],
folders: [
{
folder_id: "Folder1",
name: "Sub Folder",
files: [
{
file_id: "File1-1",
name: "New Microsoft Word Document.docx"
}
],
folders: [
{
folder_id: "Folder1-1",
name: "Folder Grade 2",
files: [
{
file_id: "File1-1-1",
name: "Test file in Folder Grade 3"
}
],
folders: [
{
folder_id: "Folder1-1-1",
name: "Folder Grade 3",
files: [],
folders: []
}
]
}
]
}
]
},
{
folder_id: "F2",
name: "Test Folder 2",
files: [
{
file_id: "File2",
name: "buildcode.png"
}
],
folders: [
{
folder_id: "Folder2",
name: "Sub folder 1",
files: [
{
file_id: "File2-1",
name: "repo.png"
}
],
folders: []
}
]
}
];
I want the output to look like this:
{
my-root-id:{
childrenIds:[
0: "F1",
1: "F2"
],
id: "my-root-id"
},
F1:{
childrenIds:[
0: "File1",
1: "Folder1"
],
parentId: "my-root-id",
id: "F1"
},
F2:{
childrenIds:[
0: "File2",
1: "Folder2"
],
parentId: "my-root-id",
id: "F2"
},
File1:{
parentId: "File1",
id: "F1"
},
Folder1:{
childrenIds:[
0: "File1-1",
1: "Folder1-1"
],
parentId: "F1",
id: "Folder1"
},
Folder1-1:{
childrenIds:[
0: "File1-1-1",
1: "Folder1-1-1"
],
parentId: "Folder1",
id: "Folder1-1"
},
Folder2:{
childrenIds:[
0: "File2-1",
],
parentId: "F2",
id: "Folder2"
},
File2-1:{
parentId: "Folder2",
id: "File2-1"
}
}
The output above describes the relationship of each folder and file in the entire directory tree.
They need information like :
childrenIds: the folders and files it contains
parentId: Its parent directory
id: id by itself
How to do it. thank you
Don't know this actually works for you or not but output as you look for
let data = {
folders: [
{
folder_id: "F1",
name: "Test Folder 1",
files: [
{
file_id: "File1",
name: "Whiteboard-Jun 3rd 2020, 4:56 pm",
},
],
folders: [
{
folder_id: "Folder1",
name: "Sub Folder",
files: [
{
file_id: "File1-1",
name: "New Microsoft Word Document.docx",
},
],
folders: [
{
folder_id: "Folder1-1",
name: "Folder Grade 2",
files: [
{
file_id: "File1-1-1",
name: "Test file in Folder Grade 3",
},
],
folders: [
{
folder_id: "Folder1-1-1",
name: "Folder Grade 3",
files: [],
folders: [],
},
],
},
],
},
],
},
{
folder_id: "F2",
name: "Test Folder 2",
files: [
{
file_id: "File2",
name: "buildcode.png",
},
],
folders: [
{
folder_id: "Folder2",
name: "Sub folder 1",
files: [
{
file_id: "File2-1",
name: "repo.png",
},
],
folders: [],
},
],
},
],
};
const mapper = (folders, parentId) => {
let obj = {};
if (folders.length) {
folders.forEach((f) => {
if (f.folders) {
let _c = {
[f.folder_id]: {
childrenIds: f.files.map((_f) => _f.file_id),
...(parentId && { parentId }),
id: f.folder_id,
},
};
let _files = f.files.map((_f) => {
return {
[_f.file_id]: { ...(parentId && { parentId }), id: _f.file_id },
};
});
obj = { ...obj, ..._files["0"], ..._c, ...mapper(f.folders, f.folder_id) };
}
});
}
return obj;
};
console.log(mapper(data.folders));
Related
I have an array that I like to group by the ID, but pushing all the different elements in the arrays in the result.
let data = [
{ id: "1", elements: ["a","b"], files: [] },
{ id: "1", elements: ["a","b"], files: [] },
{ id: "2", elements: ["a","b","c"],
files: [
{ name: "test1",
extension: "pdf"
},
{ name: "test2",
extension: "pdf"
}
]
},
{ id: "2", elements: ["a","b","c"],
files: [
{ name: "test3",
extension: "png"
},
{ name: "test4",
extension: "png"
},
{ name: "test5",
extension: "pdf"
}
]
},
{ id: "2", elements: ["a","b","c"], files: []
}
];
I want a result like
result =
[
{
"id": "1", "elements": [ "a", "b" ], "files": [] },
{
"id": "2", "elements": [ "a", "b", "c" ],
"files": [
{ "name": "test1", "extension": "pdf" },
{ "name": "test2", "extension": "pdf" },
{ "name": "test3", "extension": "png" },
{ "name": "test4", "extension": "png" },
{ "name": "test5", "extension": "pdf" },
]
}
]
How it is possible with lodash or any other process getting the desire output
You can use Array.reduce() to group the items by id.
This creates an object with a property for each id, we can then use Object.values() to get the result as an array.
For the elements array, we'll also use a Set to ensure we don't duplicate elements. We only want ['a','b'] rather than ['a','b','a','b'] for example.
let data = [ { id: "1", elements: ["a","b"], files: [] }, { id: "1", elements: ["a","b"], files: [] }, { id: "2", elements: ["a","b","c"], files: [ { name: "test1", extension: "pdf" }, { name: "test2", extension: "pdf" } ] }, { id: "2", elements: ["a","b","c"], files: [ { name: "test3", extension: "png" }, { name: "test4", extension: "png" }, { name: "test5", extension: "pdf" } ] }, { id: "2", elements: ["a","b","c"], files: [] } ];
const result = Object.values(data.reduce((acc, { id, elements, files }) => {
acc[id] = acc[id] || { id, elements: [], files: []};
// Use a Set to avoid duplicates...
acc[id].elements = [...new Set([...elements, ...acc[id].elements])];
acc[id].files.push(...files);
return acc;
}, {}));
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }
I have a deep level array like below,
const cat = [
{
name: "cat 1",
id: 1,
subCat: [
{
name: "sub 1",
id: 10,
subSubCat: [
{ summary: "summary1", id: 20 },
{ summary: "summary2", id: 21 },
],
},
],
},
{
name: "cat 2",
id: 2,
subCat: [
{
name: "sub 2",
id: 20,
subSubCat: [
{ summary: "summary1", id: 30 },
{ summary: "summary2", id: 31 },
],
},
],
},
];
I have to filter with subSubCat id(31) and it should return a summary value(summary2).
You can use Array.map and Array.flat to get the subSubCat list, then use Array.find to find the subSubCat item by id.
const cat = [
{
name: "cat 1",
id: 1,
subCat: [
{
name: "sub 1",
id: 10,
subSubCat: [
{ summary: "summary1", id: 20 },
{ summary: "summary2", id: 21 },
],
},
],
},
{
name: "cat 2",
id: 2,
subCat: [
{
name: "sub 2",
id: 20,
subSubCat: [
{ summary: "summary1", id: 30 },
{ summary: "summary2", id: 31 },
],
},
],
},
];
var subSubCats = cat.map(item => item.subCat.map(subCatItem => subCatItem.subSubCat)).flat(2);
var result = subSubCats.find(e => e.id == 31);
console.log(result.summary);
This looks like something that requires a two level loop and find().
const cat = [
{
name: "cat 1",
id: 1,
subCat: [
{
name: "sub 1",
id: 10,
subSubCat: [
{ summary: "summary1", id: 20 },
{ summary: "summary2", id: 21 },
],
},
],
},
{
name: "cat 2",
id: 2,
subCat: [
{
name: "sub 2",
id: 20,
subSubCat: [
{ summary: "summary1", id: 30 },
{ summary: "summary2", id: 31 },
],
},
],
},
];
for(let i =0 ; i < cat.length;i++){
if(Array.isArray(cat[i].subCat)){
let subCatArray = cat[i].subCat;
//console.log(subCatArray);
for(let j =0 ; j < subCatArray.length;j++){
let subSubArray = subCatArray[j].subSubCat;
if(Array.isArray(subSubArray)){
//console.log(subSubArray);
let foundObject = subSubArray.find((x) =>
x.id === 31
);
//console.log(foundObject);
if(foundObject!==undefined)
{
console.log(foundObject.summary);
break;
}
}
}
}
}
How to return name and id property value of all arrays? The idea is to make a single map of all these arrays and return the id and name?
Something like this
filters.[key].map((option, index) => (
<ItemFilter key={index}>{option}</ItemFilter>
))
I have this array object
filters: {
"services": [
{
"id": "1b975589-7111-46a4-b433-d0e3c0d7c08c",
"name": "Bank"
},
{
"id": "91d4637e-a17f-4b31-8675-c041fe06e2ad",
"name": "Income"
}
],
"accountTypes": [
{
"id": "1f34205b-2e5a-430e-982c-5673cbdb3a68",
"name": "Digital Account"
}
],
"channels": [
{
"id": "875f8350-073e-4a20-be20-38482a86892b",
"name": "Chat"
}
]
}
You can use flatMap or flat to achieve the desired result.
Object.values(obj.filters).flatMap(v => v)
or
Object.values(obj.filters).flat()
const obj = {
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
};
const result = Object.values(obj.filters).flatMap(v => v);
console.log(result);
If option is referring to name in your example code it could look something like this:
Object.values(
{
filters: {
services: [
{
id: "1b975589-7111-46a4-b433-d0e3c0d7c08c",
name: "Bank",
},
{
id: "91d4637e-a17f-4b31-8675-c041fe06e2ad",
name: "Income",
},
],
accountTypes: [
{
id: "1f34205b-2e5a-430e-982c-5673cbdb3a68",
name: "Digital Account",
},
],
channels: [
{
id: "875f8350-073e-4a20-be20-38482a86892b",
name: "Chat",
},
],
},
}.filters
)
.flat()
.map(({ name, index }) => <ItemFilter key={index}>{name}</ItemFilter>);
I want to filter out of a deeply nested data structure all the objects that match a rule. I know there are similar examples to delete a particular key of nested object, but I haven't been able to implement the solutions. The data structure will never be infinite, but it can be very deep (more than 10 levels)
Here are the types:
export type DataStructure = Entry[]
export interface Entry {
id: string
text: string
type: 1 | 2
children?: Entry[]
}
So an entry array could be:
[
{
id: "1",
type: 1,
text: "Node 1",
children: [
{
id: "1.1",
type: 1,
text: "Node 1.1",
children: [
{
id: "1.1.1",
type: 2,
text: "Node 1.1.1",
children: []
}
],
},
{
id: "1.2",
type: 1,
text: "Node 1.2",
children: [
{
id: "1.2.1",
type: 2,
text: "Node 1.2.1",
children: [],
},
{
id: "1.2.2",
type: 1,
text: "Node 1.2.2",
children: [],
}
]
}
]
}
]
The expected output array, provided the rule type !== 2 would be:
[
{
id: "1",
type: 1,
text: "Node 1",
children: [
{
id: "1.2",
type: 1,
text: "Node 1.2",
children: [
{
id: "1.2.2",
type: 1,
text: "Node 1.2.2",
children: [],
}
]
}
]
}
]
I haven't been able to implement recursion to do it, the arrays keep showing all the entries
I don't mind using lodash if there is a built-in function. Thanks!
If you want to filter based on type:
function test() {
const test = [
{
id: "1",
type: 1,
text: "Node 1",
children: [
{
id: "1.1",
type: 1,
text: "Node 1.1",
children: [
{
id: "1.1.1",
type: 1,
text: "Node 1.1.1",
children: []
}
],
},
{
id: "1.2",
type: 2,
text: "Node 1.2",
children: [
{
id: "1.2.1",
type: 2,
text: "Node 1.2.1",
children: [],
},
{
id: "1.2.2",
type: 2,
text: "Node 1.2.2",
children: [],
}
]
}
]
}
];
console.log(JSON.stringify(filterData(test, 2), 0, 4))
console.log('test: ', test);
}
and filter method:
function filterData(data, type) {
var r = data.filter(function(o) {
if (o.children)
o.children = filterData(o.children, type);
return o.type != type
})
return r;
}
I had reformat my data in mongodb using ancestors path to ensure the relationship of each nodes & intend to show it in a organisation tree view.
[
{
"isActive": true,
"ancestorsPath": [],
"studentGroup": [
"t2-001",
"t2-002",
"t2-003"
],
"_id": "33d9704f34901855c911e433",
"email": "user5#test.com",
"agentId": "t1-001"
},
{
"isActive": true,
"ancestorsPath": [],
"studentGroup": [
"t2-101",
"t2-102",
"t2-103"
],
"_id": "5cdb0664c409e90e4fe21133",
"email": "user5#test.com",
"agentId": "t1-100",
},
{
"isActive": true,
"ancestorsPath": [
"t1-001"
],
"studentGroup": [
"t3-001",
"t3-002",
"t3-003"
],
"_id": "5cdb06dec409e90e4fe21134",
"email": "user5#test.com",
"agentId": "t2-001",
}
]
However the data in organisation tree is using a format as below:
id: "T1-001",
name: "user5#test.com",
title: "general manager",
children: [
{
id: "t2-001",
name: "Bo Miao",
title: "department manager",
number: "MYR 2,000"
},
{
id: "t2-002",
name: "Su Miao",
title: "department manager",
children: [
{ id: "t3-001", name: "Tie Hua", title: "senior engineer" },
{
id: "t3-002",
name: "Hei Hei",
title: "senior engineer",
children: [
{ id: "6", name: "Pang Pang", title: "engineer" },
{ id: "7", name: "Xiang Xiang", title: "UE engineer" }
]
}
]
},
{ id: "t2-003", name: "Hong Miao", title: "department manager" }
How should I format my data? Can anyone give me some pointers so i can study further?