Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript equivalent of Python's dict.setdefault?

In Python, for a dictionary d,

d.setdefault('key', value)

sets d['key'] = value if 'key' was not in d, and otherwise leaves it as it is.

Is there a clean, idiomatic way to do this on a Javascript object, or does it require an if statement?

like image 831
ptomato Avatar asked Apr 19 '13 15:04

ptomato


People also ask

What is equivalent of Dictionary in JavaScript?

Actually there is no 'dictionary' type in JavaScript but we can create key-value pairs by using JavaScript Objects. Create a new JavaScript Object which will act as dictionary. Syntax: Key can be a string , integer. If you just write key1 or any number, it will treat as a string.

What is Setdefault () method in Dictionary?

The setdefault() method returns the value of a key (if the key is in dictionary). If not, it inserts key with a value to the dictionary. The syntax of setdefault() is: dict.setdefault(key[, default_value])

Is there a Dictionary in JavaScript?

Are there dictionaries in JavaScript? No, as of now JavaScript does not include a native “Dictionary” data type. However, Objects in JavaScript are quite flexible and can be used to create key-value pairs. These objects are quite similar to dictionaries and work alike.

Are JavaScript objects like Python dictionaries?

The data stored in the form of key-value pairs is called an Object or a Dictionary. Objects and dictionaries are similar; the difference lies in semantics. In JavaScript, dictionaries are called objects, whereas, in languages like Python or C#, they are called dictionaries.


6 Answers

if (!('key' in d)) d.key = value;

or

'key' in d || (d.key = value);

(The last one uses the short-circuit behavior of conditional expressions.)


"d.key || (d.key = value)" suggested in the other answer is buggy: if an element exists but evaluates to false (false, null, 0, -0, "", undefined, NaN), it will be silently overwritten.

  • While this might be intended, it's most probably not intended for all of the aforementioned cases. So in such a case, check for the values separately:

    if (!('key' in d) || d.key === null) d.key = value;
    
like image 139
bobtato Avatar answered Oct 09 '22 21:10

bobtato


It's basically like using an if statement, but shorter:

d.key || (d.key = value);

Or

d.key = d.key || value;

Update: as @bobtato noted, if the property is already set to the value false it would overwrite it, so a better way would be:

!d.key && d.key !== false && (d.key = value);

Or, to do it as he suggested (just the shorthanded version):

'key' in d || (d.key = value);

// including overwriting null values:

('key' in d && d.key !== null) || (d.key = value);
like image 28
roberkules Avatar answered Oct 09 '22 21:10

roberkules


Nowadays you can also do d.key ??= value

like image 23
muodov Avatar answered Oct 09 '22 20:10

muodov


There is nothing built-in, but this function will do it:

function setDefault(obj, prop, deflt) {
  return obj.hasOwnProperty(prop) ? obj[prop] : (obj[prop] = deflt);
}

If obj will only contain non-falsy values, obj[prop] || (obj[prop] = deflt) is a fine simple alternative (but deflt will override anything falsy). This has the added advantage that deflt will only get evaluated when its value is needed, so it's OK for it to be an expensive expression.

like image 35
DS. Avatar answered Oct 09 '22 21:10

DS.


a={}
key='3'
value = 2
a[key] = a[key] == undefined ? value : a[key]

## a = {'3': 2 }
like image 2
RAM Avatar answered Oct 09 '22 20:10

RAM


It's not recommended and is never a good idea to augment the built-in classes. Instead, it's better to create your own implementations of built-in classes, a lot like the YUI library does (YArray, etc). However, I'm going to contradict that, because I often find that implementing useful short cuts like this are a benefit to writing clean maintainable code:

if (undefined === Object.prototype.setdefault) {
    Object.prototype.setdefault = function(key, def) {
        if (! this.hasOwnProperty(key)) {
            this[key] = def;
        }
        return this[key];
    };
}

So let's see it in action...

var a = {};

a.setdefault('mylist', []).push(1);
a.setdefault('mylist', []).push(2);

console.log(a.mylist.toString());
    1,2

As has been pointed out, it's never a good idea to employ thing = thing || defaultThing because it only tests non-typed equality of true, or thing == true. As opposed to typed equality: thing === true or thing !== undefined. So the only way to properly code setdefault in an inline way would be to use this snippet everywhere:

/* null == thing is equivalent to... */
if (undefined !== thing && null !== thing) {
    thing = defaultThing;
}
/* ...but it's not explicit and linters don't like it! */

But as I already said, this just adds bloat to your code and is prone to errors acquired from "copy-and-paste" syndrome.

like image 6
Craig Avatar answered Oct 09 '22 22:10

Craig