Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
167 lines (114 sloc) 3.88 KB

JavaScript-Defaultdict

This project tries to emulate the python dictionary class defaultdict.

Simple usage

var addressMap = defaultdict('Unknown');

addressMap['bob'] = 'CA';

console.log(addressMap.bob); //CA
console.log(addressMap('bob')); //CA

console.log(addressMap('jil')); //Unknown

//the default value will be assigned to the key

console.log(addressMap.jil); //Unknown    


addressMap = addressMap.toObject(); // {bob:'CA',jil:'Unknown'}

Functions as a defaultvalue

var presents = ['shoes','phone','tv','xbox'];

var presentsMap = defaultdict(function(){return presents.pop();});

presentsMap['bob'] = 'computer';

console.log(presentsMap('bob')); // computer

console.log(presentsMap('jil')); // xbox

console.log(presentsMap('alice')); // tv

Advanced usage with nested defaultdicts

Suppose we have a records stored somewhere that are in this format

STATE               CITY                        MAKE
CA              San Francisco                   Ford
CA              San Francisco                   Ford
CA              San Francisco                   BWM
CA              San Jose                        Lexus
FL              Miami                           Honda
......

And we wanted to to get make an object that has the counts of each make organized by state, and city. That would look something like

var carsInEachCity = {
    'CA':{
        'San Francisco':{
            'Ford':2000,
            'Nissan': 400,
            'Honda': 5
        },
        'San Jose':{
            'BMW': 7575,
            'Lexus': 56
        }
    },
    'FL':{
        'Miami':{
            'Ford':2000,
            'Nissan': 400,
            'Honda': 5
        },

        'Orlando':{
            'Ford':23,
            'Nissan': 897,
            'Honda': 52,
            'GM': 3456
        }   
    }
}

Usually one would loop through the records and do something like

var carsInEachCity = {};

var records = [
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'Honda'},
                {state:'FL',city:'Miami',make:'Honda'},
                {state:'FL',city:'Miami',make:'Lexus'},
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'BMW'},
              ];

records.forEach(function(o){

    if(!carsInEachCity[o.state])
        carsInEachCity[o.state] = {};

    if(!carsInEachCity[o.state][o.city])
        carsInEachCity[o.state][o.city] = {};

    if(!carsInEachCity[o.state][o.city][o.make])
        carsInEachCity[o.state][o.city][o.make] = 0;

    carsInEachCity[o.state][o.city][o.make]++;

});

console.log(carsInEachCity);
console.log(carsInEachCity['CA']['San Jose']['BMW']) //4
console.log(carsInEachCity['CA']['San Jose']['Jeep']) //undefined

You can imagine the code getting pretty ugly the more nested things get

To do the same thing with default dict

var carsInEachCity = defaultdict(function () {
    return defaultdict(function () {
        return defaultdict(0);
    });
});

var records = [
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'Honda'},
                {state:'FL',city:'Miami',make:'Honda'},
                {state:'FL',city:'Miami',make:'Lexus'},
                {state:'CA',city:'San Jose',make:'BMW'},
                {state:'CA',city:'San Jose',make:'BMW'},
            ];


records.forEach(function(o){
    carsInEachCity(o.state)(o.city)(o.make);
    carsInEachCity[o.state][o.city][o.make]++;  
});


console.log(carsInEachCity['CA']['San Jose']['BMW']) //4
console.log(carsInEachCity['CA']['San Jose']['Jeep']) //undefined
console.log(carsInEachCity('CA')('San Jose')('Jeep')) //0
console.log(carsInEachCity['CA']['San Jose']['Jeep']) //0

carsInEachCity = carsInEachCity.toObject();

console.log(carsInEachCity);
console.log(carsInEachCity['CA']['San Jose']['BMW']) //4
console.log(carsInEachCity['CA']['San Jose']['Jeep']) //0

As you can see using defaultdict makes initializing nested objects a breeze.

Tips

If you have nested default dicts the toObject method will call the toObject method on the nested default dicts as well.

Something went wrong with that request. Please try again.