3

I want to implement a nested default dictionary in javascript, so I can go

nest['first']['second']['third'] = 'yay' without having to check or initialize nest['first'] & nest['first']['second']

In python, this is pretty easy

nested = defaultDict(lambda: deafultDict(dict()))

I tried to implement the same in javascript using Proxy. The results were not as expected and I can't figure out what I'm missing. From the last logline, it looks like the same default dictionary is being passed around as a reference. How can I avoid this and make it work as expected?

function defaultDict (defaultValue) {
  const handler = {
    get: (obj, prop) => {
      return prop in obj ? obj[prop] : defaultValue
    }
  }
  return new Proxy({}, handler)
}

var nested = defaultDict(defaultDict({}))

nested['first']['second']['third'] = 'yay'

console.log(nested['first']['second']['third']) // yay  OK
console.log(nested['first']['second']) // {third: 'yay'} OK

console.log(nested['first']) // result: {} expected {second: {third: 'yay'}}

console.log(nested['none']['gggggggggggg']) // result: {third: 'yay'} expected: {}

thanks!

2
  • Well, yes, your innermost {} in defaultDict(defaultDict({})) is a single plain object. Commented Sep 18, 2020 at 11:03
  • sure, but the last logline is printing {third: 'yay'} and not {} as expected Commented Sep 18, 2020 at 11:04

1 Answer 1

2

To achieve an arbitrarily deep autovivifying object, you'll want something like

function defaultDict(defaultValueFn) {
  const handler = {
    get: (obj, prop) => {
      if(!(prop in obj)) obj[prop] = defaultValueFn();
      return obj[prop];
    },  
  };
  return new Proxy({}, handler);
}

var nestedDefaultDict = () => defaultDict(nestedDefaultDict);
var nested = nestedDefaultDict();

nested.a.b.c = 8;
nested.d.e.f = 8;
console.log(nested); // { a: { b: { c: 8 } }, d: { e: { f: 8 } } }

, that is just like in the Python defaultdict, you pass in a callable that returns the nested object, not the object itself.

Sign up to request clarification or add additional context in comments.

2 Comments

this does not give me the expected results unfortunately jsfiddle.net/6k8m1wth
Sorry, fixed. I missed that we didn't actually insert the new object into the proxied object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.