Multiple key names, same pair value

I'm trying to setup an object literal in a JavaScript script that has a key with multiple names. referring to the same object value i.e. something like these that I have already tried:

var holidays: {
    "thanksgiving day", "thanksgiving", "t-day": {
        someValue : "foo"
    }
}

var holidays: {
    ["thanksgiving day", "thanksgiving", "t-day"]: {
        someValue : "foo"
    }
}

Is there a way I can accomplish this?


Another approach is to do some postprocessing

function expand(obj) {
    var keys = Object.keys(obj);
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i],
            subkeys = key.split(/,\s?/),
            target = obj[key];
        delete obj[key];
        subkeys.forEach(function(key) { obj[key] = target; })
    }
    return obj;
}

var holidays = expand({
    "thanksgiving day, thanksgiving, t-day": {
        someValue : "foo"
    } 
});

JSON does not offer such a feature, nor do Javascript object literals.

You might be able to make do with something like this:

holidays = {
    thanksgiving: {foo: 'foo'},
    groundhogDay: {foo: 'bar'},
    aliases: {
        'thanksgiving day': 'thanksgiving',
        't-day': 'thanksgiving',
        'Bill Murrays nightmare': 'groundhogDay'
    }
}

and then you can check

holidays[name] || holidays[holidays.aliases[name]]

for your data.

It's not a wonderful solution. But it wouldn't be too difficult to write a little function that created this sort of object out of a representation like:

[
    {
        names: ['thanksgiving', 'thanksgiving day', 't-day'],
        obj: {foo: 'foo'}
    },
    {
        names: ['groundhogDay', 'Bill Murrays nightmare'],
        obj: {foo: 'bar'}
    },
]

if that would be easier to maintain.


Another solution, if you can afford RegExp execution, and ES6 Proxy:

let align = new Proxy({
    
    'start|top|left': -1,
    'middle|center': 0,
    'end|bottom|right': 1,

}, {

    get: function(target, property, receiver) {

        for (let k in target)
            if (new RegExp(k).test(property))
                return target[k]

        return null

    }

})

align.start     // -1
align.top       // -1
align.left      // -1

align.middle    // 0
align.center    // 0

align.end       // 1
align.bottom    // 1
align.right     // 1

See MDN Proxy

2021 EDIT:
Another (cleaner?) solution using reduce & defineProperty :

const myDict = [
    // list of pairs [value, keys],
    // note that a key should appear only once
    [-1, ['start', 'left', 'top']],
    [0, ['center', 'middle']],
    [1, ['end', 'right', 'bottom']],
].reduce((obj, [value, keys]) => {
    for (const key of keys) {
        Object.defineProperty(obj, key, { value })
    }
    return obj
}, {})

I guess you could do something like this:

var holidays = {
  'thanksgiving day': {
    foo: 'foo'
  }
};

holidays.thanksgiving = holidays['t-day'] = holidays['thanksgiving day'];

If you see yourself doing this often or you have more values consider this pattern:

'thanksgiving, t-day, thanks, thank, thank u'.split(',').forEach(function(key) {
  holidays[key] = holidays['thanksgiving day'];
});

A better approach would be to process your data beforehand instead of adding duplicates.


That should work as expected:

function getItem(_key) {
    items = [{
        item: 'a',
        keys: ['xyz','foo']
    },{
        item: 'b',
        keys: ['xwt','bar']
    }];

    _filtered = items.filter(function(item) {
        return item.keys.indexOf(_key) != -1
    }).map(function(item) {
        return item.item;
    });
    return !!_filtered.length ? _filtered[0] : false;
}