Skip to Content
UtilsTransform Lists & Trees

Transform Lists and Nested Structures

This guide shows how to convert common data structures for better access, mutation, and integration — including lists, trees, dictionaries, and flattened arrays.

🔁 List to Tree

This utility transforms a flat list of items (with id and parentId fields) into a nested tree structure. It uses a Map to efficiently link children to their parents while preserving the hierarchy.

It also includes a treeToList() function that flattens a tree back into a list — useful for data normalization, storing tree nodes in databases, or syncing front-end trees with backend updates.

listToTree
function listToTree(items) { const map = new Map(); const roots = []; // Map items by ID for (const item of items) { map.set(item.id, { ...item, children: [] }); } for (const item of items) { const node = map.get(item.id); if (item.parentId === null) { roots.push(node); } else { const parent = map.get(item.parentId); if (parent) { parent.children.push(node); } } } return roots; } const items = [ { id: 1, name: "Root 1", parentId: null }, { id: 2, name: "Child 1.1", parentId: 1 }, { id: 3, name: "Child 1.2", parentId: 1 }, { id: 4, name: "Root 2", parentId: null }, { id: 5, name: "Child 2.1", parentId: 4 }, { id: 6, name: "SubChild 2.1.1", parentId: 5 }, ]; const tree = listToTree(items); console.log(tree); // [ // { // "id": 1, // "name": "Root 1", // "parentId": null, // "children": [ // { // "id": 2, // "name": "Child 1.1", // "parentId": 1, // "children": [] // }, // { // "id": 3, // "name": "Child 1.2", // "parentId": 1, // "children": [] // } // ] // }, // { // "id": 4, // "name": "Root 2", // "parentId": null, // "children": [ // { // "id": 5, // "name": "Child 2.1", // "parentId": 4, // "children": [ // { // "id": 6, // "name": "SubChild 2.1.1", // "parentId": 5, // "children": [] // } // ] // } // ] // } // ] function treeToList(tree) { const list = []; function traverse(node) { const { children, ...rest } = node; list.push(rest); if (children) { for (const child of children) { traverse(child); } } } for (const root of tree) { traverse(root); } return list; } const flatList = treeToList(tree); console.log(flatList); // [ // { id: 1, name: 'Root 1', parentId: null }, // { id: 2, name: 'Child 1.1', parentId: 1 }, // { id: 3, name: 'Child 1.2', parentId: 1 }, // { id: 4, name: 'Root 2', parentId: null }, // { id: 5, name: 'Child 2.1', parentId: 4 }, // { id: 6, name: 'SubChild 2.1.1', parentId: 5 } // ]

🧩 Flat Nested Items (With Category + Subcategory)

Transforms deeply nested category-subcategory-item data into a flat array where each item contains metadata about its parent subcategory and category.

You can do it manually with loops or concisely with flatMap().

flatNested
const data = [ { id: 1, name: "Category A", items: [ { id: 2, name: "Subcategory A1", items: [ { id: 3, name: "Item A1-1", value: 10 }, { id: 4, name: "Item A1-2", value: 15 }, ], }, { id: 5, name: "Subcategory A2", items: [ { id: 6, name: "Item A2-1", value: 20 }, { id: 7, name: "Item A2-2", value: 25 }, ], }, ], }, { id: 8, name: "Category B", items: [ { id: 9, name: "Subcategory B1", items: [ { id: 10, name: "Item B1-1", value: 30 }, { id: 11, name: "Item B1-2", value: 35 }, ], }, { id: 12, name: "Subcategory B2", items: [ { id: 13, name: "Item B2-1", value: 40 }, { id: 14, name: "Item B2-2", value: 45 }, ], }, ], }, ]; function transformItems(data) { const transformedItems = []; for (const category of data) { for (const subcategory of category.items) { for (const item of subcategory.items) { transformedItems.push({ id: item.id, name: item.name, value: item.value, subcategory: subcategory.name, category: category.name, }); } } } return transformedItems; } const itemsWithCategories = transformItems(data); console.log(itemsWithCategories); // [ // { // id: 3, // name: "Item A1-1", // value: 10, // subcategory: "Subcategory A1", // category: "Category A", // }, // { // id: 4, // name: "Item A1-2", // value: 15, // subcategory: "Subcategory A1", // category: "Category A", // }, // { // id: 6, // name: "Item A2-1", // value: 20, // subcategory: "Subcategory A2", // category: "Category A", // }, // { // id: 7, // name: "Item A2-2", // value: 25, // subcategory: "Subcategory A2", // category: "Category A", // }, // { // id: 10, // name: "Item B1-1", // value: 30, // subcategory: "Subcategory B1", // category: "Category B", // }, // { // id: 11, // name: "Item B1-2", // value: 35, // subcategory: "Subcategory B1", // category: "Category B", // }, // { // id: 13, // name: "Item B2-1", // value: 40, // subcategory: "Subcategory B2", // category: "Category B", // }, // { // id: 14, // name: "Item B2-2", // value: 45, // subcategory: "Subcategory B2", // category: "Category B", // }, // ]; function transformItems2(data) { return data.flatMap((category) => category.items.flatMap((subcategory) => subcategory.items.map((item) => ({ id: item.id, name: item.name, value: item.value, subcategory: subcategory.name, category: category.name, })), ), ); } const itemsWithCategories2 = transformItems2(data); console.log(itemsWithCategories2); // ...same result
Last updated on