What steps are needed to build a Nested Default Dictionary in JavaScript?

I've been working on creating an Apps Script and have run into a challenge with implementing a Default Dictionary. Initially, I tried using the following code snippet:

class DefaultDict {
  constructor(defaultInit) {
    return new Proxy({}, {
      get: (target, name) => name in target ?
        target[name] :
        (target[name] = typeof defaultInit === 'function' ?
          new defaultInit().valueOf() :
          defaultInit)
    })
  }
}

While this approach worked for creating a flat Default Dictionary using

let locationDict = new DefaultDict(Array)
, or new DefaultDict(Number), it failed when used with nested instances like
new DefaultDict(DefaultDict(Array))
.

The error encountered was

TypeError: Class constructor DefaultDict cannot be invoked without 'new'
, which was puzzling as I assumed the use of the new keyword within the class constructor would handle constructor invocations.

To resolve this issue, I transformed the class into a function:

function DefaultDict (defaultInit) {
  const handler = {
    get: (target, name) => name in target ?
      target[name] :
      (target[name] = typeof defaultInit === 'function' ?
        new defaultInit().valueOf() :
        defaultInit)
  }
  return new Proxy({}, handler)
}

Initially, it seemed to work fine even with nested instances, until running the code with actual data revealed discrepancies. To simplify, consider the following example:

   const data = [["Welcome to El Mirage Sign", "El Mirage", "Arizona", "United States"],
                 ["Indian Roller Bird", "Austin", "Texas", "United States"],
                 ["Greenbrier Park Half-Court", "Austin", "Texas", "United States"],
                 ["Pink Dinosaur Playscape", "Austin", "Texas", "United States"]]
  const caption = 0
  const subregion = 1
  const region = 2
  const country = 3
  
  let locationDict = new DefaultDict(DefaultDict(DefaultDict(Array)))
  for (let i = 0; i < data.length; i++)
  {
    const caption = data[i][0]
    const subregion = data[i][1]
    const region = data[i][2]
    const country = data[i][3]
    locationDict[country][region][subregion].push(caption)
  }

  console.log(locationDict)

The output displayed was not as expected, with some shared values among regions. The desired result should look more like this:

{
  'United States': 
  {
    Arizona:
    {
      'El Mirage': ["Welcome to El Mirage Sign"]
    },
    Texas:
    {
      Austin: ["Indian Roller Bird", "Greenbrier Park Half-Court", "Pink Dinosaur Playscape"]
    }
}

This discrepancy has left me unsure about the next steps to take. Any assistance or guidance would be greatly appreciated. Thank you!

Answer №1

Ensure that the argument passed to new DefaultDict() is a function, not just a value. This function should return a DefaultDict for the nested value.

Remember to avoid using new when calling it since it may not necessarily be a constructor function of a class. Instead, provide a function that can return an instance of a class, like the nested DefaultDict.

Although your proxy allows for the argument to be an instance, this might not be suitable in this scenario. Creating the parent DefaultDict will result in a single instance being used throughout, with all elements referring back to this same instance.

class DefaultDict {
  constructor(defaultInit) {
    return new Proxy({}, {
      get: (target, name) => name in target ?
        target[name] :
        (target[name] = typeof defaultInit === 'function' ?
          defaultInit().valueOf() :
          defaultInit)
    })
  }
}

let myDict = new DefaultDict(() => new DefaultDict(Number));

myDict.abc.x = 1;
myDict.abc.y = 2;
myDict.def.x = 3;
myDict.def.y = 4;

console.log(myDict.abc.x, myDict.abc.y, myDict.abc.z, myDict.def.x, myDict.def.y, myDict.def.z);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Encountering an error: "Unable to assign the 'id' property to an undefined object while attempting to retrieve it"

I'm running into an issue while attempting to retrieve a specific user from Firebase's Firestore. export class TaskService { tasksCollection: AngularFirestoreCollection<Task>; taskDoc: AngularFirestoreDocument<Task>; tasks: Obs ...

Prevent form submission once all tasks have been finalized

Hey there, I've been racking my brain for hours trying to solve this issue... I'm looking to disable my form after it's been submitted to prevent multiple submissions. However, every method I try seems to disable the button but also interfe ...

Unable to execute context function in React due to an issue

Attempting to update the state of a context from a child Component, but encountering an issue where the context function is not being invoked. To provide some context, here is an example snippet data passed to handleModal in Dashboard.jsx: { _id: "123", ...

Webpack is unable to locate a specific custom JavaScript file

Currently, we are in the process of transitioning from grunt to webpack for our project. Within our project, we have a JS file named boiler that is used to define the core classes which are frequently accessed. __boiler__.js define(function (require) { ...

"An error occurred when processing the JSON data, despite the JSON

Incorporating Ajax syntax for datatables and angularjs has been my current endeavor. Encountering an invalid JSON response with the following: self.dtOptions = DTOptionsBuilder.fromSource([{ "id": 860, "firstName": "Superman", "lastName": "Yoda" }]) How ...

Metronome in TypeScript

I am currently working on developing a metronome using Typescript within the Angular 2 framework. Many thanks to @Nitzan-Tomer for assisting me with the foundational concepts, as discussed in this Stack Overflow post: Typescript Loop with Delay. My curren ...

Encountered an error while attempting to complete the 'send' action with 'XMLHttpRequest'

I am currently developing a Cordova application that makes use of ajax. Everything works perfectly during debugging, but once I build the release version, I encounter this error: {"readyState":0,"status":0,"statusText":"NetworkError: Failed to execute &ap ...

Getting an error message like "npm ERR! code ENOTFOUND" when trying to install Angular CLI using the command "

Currently, I am eager to learn Angular and have already installed Node version 18.13.0. However, when attempting to install Angular CLI using the command npm install -g @angular/cli, I encountered an issue: npm ERR! code ENOTFOUND' 'npm ERR! sys ...

Dynamically importing files in Vue.js is an efficient way to

Here's the code snippet that is functioning correctly for me var Index = require('./theme/dir1/index.vue'); However, I would like to utilize it in this way instead, var path = './theme/'+variable+'/index.vue'; var Inde ...

Trouble arises when trying to open a new window using the Angular 8 CDK

I am attempting to open my component in a new window, similar to this example: https://stackblitz.com/edit/angular-open-window However, when the window opens, my component is not displayed and I receive the following error in the console: Error: Must pro ...

What is the correct method to authenticate a user's ID token in Firestore with Javascript?

I am in the process of developing a react native application and have integrated Firebase, specifically firestore, for data management purposes. My current goal is to incorporate an automatic login feature in my app, where users remain signed in even after ...

What could be causing the failure of the JSON parse for dynamic link parameters?

I am currently attempting to pass parameters to a dynamic page within an Amplify/NextJS application. This is still a work in progress. My objective is to utilize the passed parameters to generate a basic page based on 4 parameters included in the URL invo ...

Using Jade language in a standard web application without the need for Node.js

Can Jade be utilized in a traditional web application without reliance on Node.js? This question might seem unconventional considering Jade is built for Node, but I'm curious to know if its functionality can extend beyond the Node environment. ...

Fade In/Out Scroll Effect

As the user scrolls down the page, I have a slider that smoothly slides from right to left. What I'm trying to achieve is for the slider to fade out when the last slide is no longer in view during downward scrolling, and fade back in as the last slid ...

Aurelia's numerous applications spread across various pages

Currently, I am in the process of finalizing the initial release of a large-scale website built using PHP (Phalcon), MySQL, and JQuery. The technology stack may be a bit outdated, but it was originally prototyped years ago and due to various circumstances, ...

Using Vue.js to dynamically update values in JavaScript code or tags

I've encountered an issue that I'm having trouble articulating, but I'll do my best to explain. Upon loading the page, the following code snippet, which uses jinja-based placeholders, is executed: <div class="ui container"> ...

UTF-8 characters not displaying correctly in Python 3 when received through WebSocket?

I am encountering an issue with sending a JavaScript unicode star character. When interpreted by Python, the unicode characters are being displayed as the letter â, both in the console and log file. Furthermore, other unicode characters also seem to be ...

The state initialization process is beginning with an [object Object] being passed into the setState function

Within the async function provided below, I am invoking stationData to verify that an array of objects is being passed into bartData (which currently consists of an empty array). Upon exploration, I have observed a response containing the anticipated array ...

Having trouble getting ng-click to function properly in TypeScript

I've been struggling to execute a function within a click function on my HTML page. I have added all the TypeScript definition files from NuGet, but something seems to be going wrong as my Click Function is not functioning properly. Strangely, there a ...

Utilizing NodeJS to initiate an http request and interact with a hyperlink

I am implementing website conversion testing and want to modify this code so that 10% of the http requests also click on a specific #link within the page. What additional code do I need to achieve this? var http = require('http'); http.createSer ...