Defaultdict equivalent in javascript

前端 未结 5 1171
小蘑菇
小蘑菇 2020-12-29 22:32

In python you can have a defaultdict(int) which stores int as values. And if you try to do a \'get\' on a key which is not present in the dictionary you get zero as default

相关标签:
5条回答
  • 2020-12-29 23:21

    Check out pycollections.js:

    var collections = require('pycollections');
    
    var dd = new collections.DefaultDict(function(){return 0});
    console.log(dd.get('missing'));  // 0
    
    dd.setOneNewValue(987, function(currentValue) {
      return currentValue + 1;
    });
    
    console.log(dd.items()); // [[987, 1], ['missing', 0]]
    
    0 讨论(0)
  • 2020-12-29 23:24

    To add to Andy Carlson's answer

    If you default dict an array, you'll get a toJSON field in the resulting object. You can get rid of it by deconstructing to a new object.

    const dd = new DefaultDict(Array);
    //...populate the dict
    return {...dd};
    
    0 讨论(0)
  • 2020-12-29 23:24

    A quick dirty hack can be constructed using Proxy

    function dict(factory, origin) {
        return new Proxy({ ...origin }, {
            get(dict, key) {
                // Ensure that "missed" keys are set into
                // The dictionary with default values
                if (!dict.hasOwnProperty(key)) {
                    dict[key] = factory()
                }
    
                return dict[key]
            }
        })
    }
    

    So the following code:

    n = dict(Number, [[0, 1], [1, 2], [2, 4]])
    
    // Zero is the default value mapped into 3
    assert(n[3] == 0)
    
    // The key must be present after calling factory
    assert(Object.keys(n).length == 4)
    
    0 讨论(0)
  • 2020-12-29 23:26

    You can build one using a JavaScript Proxy

    var defaultDict = new Proxy({}, {
      get: (target, name) => name in target ? target[name] : 0
    })
    

    This lets you use the same syntax as normal objects when accessing properties.

    defaultDict.a = 1
    console.log(defaultDict.a) // 1
    console.log(defaultDict.b) // 0
    

    To clean it up a bit, you can wrap this in a constructor function, or perhaps use the class syntax.

    class DefaultDict {
      constructor(defaultVal) {
        return new Proxy({}, {
          get: (target, name) => name in target ? target[name] : defaultVal
        })
      }
    }
    
    const counts = new DefaultDict(0)
    console.log(counts.c) // 0
    

    EDIT: The above implementation only works well with primitives. It should handle objects too by taking a constructor function for the default value. Here is an implementation that should work with primitives and constructor functions alike.

    class DefaultDict {
      constructor(defaultInit) {
        return new Proxy({}, {
          get: (target, name) => name in target ?
            target[name] :
            (target[name] = typeof defaultInit === 'function' ?
              new defaultInit().valueOf() :
              defaultInit)
        })
      }
    }
    
    
    const counts = new DefaultDict(Number)
    counts.c++
    console.log(counts.c) // 1
    
    const lists = new DefaultDict(Array)
    lists.men.push('bob')
    lists.women.push('alice')
    console.log(lists.men) // ['bob']
    console.log(lists.women) // ['alice']
    console.log(lists.nonbinary) // []
    
    0 讨论(0)
  • 2020-12-29 23:37

    I don't think there is the equivalent but you can always write your own. The equivalent of a dictionary in javascript would be an object so you can write it like so

    function defaultDict() {
        this.get = function (key) {
            if (this.hasOwnProperty(key)) {
                return key;
            } else {
                return 0;
            }
        }
    }
    

    Then call it like so

    var myDict = new defaultDict();
    myDict[1] = 2;
    myDict.get(1);
    
    0 讨论(0)
提交回复
热议问题