Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Which is a better way to write an "add or initialize"?

  1. Dec 31, 2015 #1
    In my work I often find myself having to write a procedure for

    "If this key is in the map, push this element to the end of the array associated with the key; otherwise, add the key and an associated array whose single element is this one".

    I used to do this like

    Code (Text):

    if ( key in M ) { M[key].push(elem); }
    else { M[key] = [elem]; }
    but now prefer to write it like

    Code (Text):

    if ( !(key in M ) { M.[key] = new Array(); }
    Why do I like this new way if the old way is equivalent???

    Because I like as few conditional blocks as possible. I like to think in terms of "If not this, change that fact and move on to the same logic we will always move on to" rather than "If not this, enter a different block of logic".

    Please share your thoughts on this religious doctrine.

    Note: I labeled this question as JavaScript only because I had to choose a label. My code is in JavaScript, but this question can apply to other languages.
  2. jcsd
  3. Dec 31, 2015 #2

    Filip Larsen

    User Avatar
    Gold Member

    When initialization and adding can be separated (not always the case for all data structures) then your second approach is quite common and, in my opinion, a bit more clear than the former approach. I would go with the later approach whenever possible.

    Note, that in JavaScript there is another common idiom when initializing and adding that uses the or-operator. Provided that your M object only have array members, then in your case that idiom would be like
    Code (Text):

    (M[key] || (M[key] = [])).push(elem);
  4. Dec 31, 2015 #3

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    In this case, the difference is so small that it's a bit moot. How one would accomplish that is also language-dependent.

    In python, I'd probably follow the mantra that it's easier to ask for forgiveness:
    Code (Python):
    def add_element (M, key, elem) :
        try :
            M[key].append (elem)
        except KeyError :
            M[key] = [elem]
    In perl, I'd use something similar to your new method, except I'd use an end-line conditional, and to avoid not, I'd use unless:
    Code (Perl):
    sub add_element($$$) {
        my ($M, $key, $elem) = @_;
        $M->{$key} = [] unless exists $M->{$key};
        push @{$M->{$key}}, $elem;
    Update on the above: @Filip Larsen's approach also works nicely in perl:
    Code (Perl):
    sub add_element($$$) {
        my ($M, $key, $elem) = @_;
        push @{$M->{$key} or $M->{$key} = []}, $elem;
    In C++, I'd use the fact that M[key] automatically adds the key to the associative array if it's not present:
    Code (C):
    template <KeyType, ElemType>
    void add_element (
        std::unordered_map<KeyType, std::vector<ElemType>>& M,
        const KeyType& key,
        const ElemType& elem)
    Last edited: Dec 31, 2015
  5. Dec 31, 2015 #4

    Filip Larsen

    User Avatar
    Gold Member

    Now DH has started on other languages I may add that in C# (where the standard dictionary index operator getter throws exception on unknown keys) I mostly end up do something like

    Code (Text):

    void AddElement<TKey,TValue>(IDictionary<TKey,ICollection<TValue>> map, TKey key, TValue value)
      ICollection<TValue> values;
      if (!map.TryGet(key, out values)) {
        map[key] = values = new List<TValue>();
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook