Dictionary of Nested Arrays
This example demonstrates how to transform a deeply nested array structure (e.g., categories → subcategories → items) into a dictionary format for constant-time lookup by id
.
Why it matters
When working with large, hierarchical datasets (like tree structures or menu items), repeatedly using .find()
or .filter()
on nested arrays
becomes expensive and messy. By flattening them into a dictionary, you gain:
- 🔍 O(1) access time to any item by
id
- 💡 Easier updates, deletions, or traversal
- 🧱 A solid foundation for normalized state in frontend apps
This guide walks through:
- A simple nested loop approach using JavaScript
- A recursive and reusable
mapToDictionary()
helper - A strongly typed TypeScript version for enterprise-scale reliability
🔢 Plain JavaScript: Nested Loop Approach
dictionary of nested
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 createNestedDictionary(data) {
const dictionary = {};
for (const category of data) {
dictionary[category.id] = { ...category, subcategories: {} };
for (const subcategory of category.items) {
dictionary[category.id].subcategories[subcategory.id] = {
...subcategory,
items: {},
};
for (const item of subcategory.items) {
dictionary[category.id].subcategories[subcategory.id].items[item.id] =
item;
}
}
}
return dictionary;
}
const nestedDictionary = createNestedDictionary(data);
console.log(nestedDictionary[1].name); // Category A
console.log(nestedDictionary[1].subcategories[5].name); // Subcategory A2
console.log(nestedDictionary[1].subcategories[5].items[7].name); // Item A2-2
console.log(nestedDictionary[8].subcategories[12].items[14]);
// { id: 14, name: 'Item B2-2', value: 45 }
♻️ Recursive Helper: mapToDictionary()
This reusable utility recursively maps any array of nested structures into a flat dictionary by id.
dictionary of nested
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 mapToDictionary(data, keys) {
const [currentKey, ...remainingKeys] = keys;
return data.reduce((acc, item) => {
acc[item.id] = {
...item,
[currentKey || "items"]: item.items
? mapToDictionary(item.items, remainingKeys)
: undefined,
};
return acc;
}, {});
}
const nestedDictionary = mapToDictionary(data, ["subcategories", "items"]);
console.log(nestedDictionary[1].name); // Category A
console.log(nestedDictionary[1].subcategories[5].name); // Subcategory A2
console.log(nestedDictionary[1].subcategories[5].items[7].name); // Item A2-2
console.log(nestedDictionary[8].subcategories[9].items[11]);
// { id: 11, name: 'Item B1-2', value: 35, items: undefined }
📄 TypeScript: Fully Typed Nested Dictionary
The following code provides strict types and reusable functions to construct the same dictionary using TypeScript.
dictionary of nested ts
type Item = {
id: number;
name: string;
value: number;
};
type Subcategory = {
id: number;
name: string;
items: Item[];
};
type Category = {
id: number;
name: string;
items: Subcategory[];
};
type Subcategories = Record<
number,
{
name: string;
items: Record<number, Item>;
}
>;
type NestedDictionary = Record<
number,
{
name: string;
subcategories: Subcategories;
}
>;
function mapItemsToDictionary(items: Item[]) {
return items.reduce(
(acc, item) => {
acc[item.id] = item;
return acc;
},
{} as Record<number, Item>,
);
}
function mapSubcategoriesToDictionary(
subcategories: Subcategory[],
) {
return subcategories.reduce((acc, subcategory) => {
acc[subcategory.id] = {
name: subcategory.name,
items: mapItemsToDictionary(subcategory.items),
};
return acc;
}, {} as Subcategories);
}
function createNestedDictionary(
categories: Category[],
): NestedDictionary {
return categories.reduce((acc, category) => {
acc[category.id] = {
name: category.name,
subcategories: mapSubcategoriesToDictionary(
category.items,
),
};
return acc;
}, {} as NestedDictionary);
}
const data: Category[] = [
{
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 },
],
},
],
},
];
const nestedDictionary = createNestedDictionary(data);
console.log(nestedDictionary[1].name); // Category A
console.log(nestedDictionary[1].subcategories[5].name); // Subcategory A2
console.log(
nestedDictionary[1].subcategories[5].items[7].name,
); // Item A2-2
console.log(
nestedDictionary[8].subcategories[12].items[14].value,
); // 45
Last updated on