2013-02-07 14 views
9

Sto tentando di impostare un oggetto letterale in uno script JavaScript con una chiave con più nomi. riferimento allo stesso valore di oggetto vale a dire qualcosa come questi che ho già provato:Nome di più chiavi, stesso valore di coppia

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

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

C'è un modo per ottenere questo risultato?

+0

Questo non è JSON, è solo un oggetto Javascript. – Barmar

risposta

7

Un altro approccio è quello di fare un po 'di post-elaborazione

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" 
    } 
}); 
+0

Questo è meglio del mio suggerimento. Fintanto che i tuoi dati non includono virgole, vorrei andare con questa risposta. –

+0

Perché il mix di un ciclo 'for' e un' forEach'? Lo troverei più pulito da seguire con uno stile, probabilmente 'forEach'. –

+0

@ScottSauyet, hai ragione. Per prima cosa ho usato 'for' perché sapevo che il suo corpo non sarebbe così piccolo, mentre quando eseguivo l'iterazione delle sottochiavi eseguivo solo una istruzione, quindi ero troppo pigro per scrivere' for (var blah ... '. Ma c'è nessun motivo per mescolare entrambi gli stili, certo –

3

Credo che si potrebbe fare qualcosa di simile:

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

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

Se vedere voi stessi facendo questo spesso o si dispone di più valori considerano questo modello:

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

Un approccio migliore sarebbe quello di elaborare i tuoi dati in anticipo invece di aggiungere duplicati.

+0

Nel caso in cui qualcuno sia curioso di sapere come funziona: In JavaScript, gli oggetti sono memorizzati per riferimento (mentre numeri e stringhe letterali, che possono essere copiati). Qui, memorizzando un * riferimento * a un oggetto che contiene il valore, quando si modifica il valore in qualsiasi modo, tutte le altre proprietà possono accedere al nuovo valore utilizzando lo stesso riferimento. – rvighne

6

JSON non offre questa funzionalità, né i valori letterali degli oggetti Javascript.

Potreste essere in grado di fare che fare con qualcosa di simile:

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

e quindi è possibile controllare

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

per i dati.

Non è una soluzione meravigliosa. Ma non sarebbe troppo difficile da scrivere un po 'la funzione che ha creato questa sorta di oggetto di una rappresentazione come:

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

se questo sarebbe più facile da mantenere.

0

Ho avuto questo problema e questo è ciò che mi si avvicinò con

function objectDive(parent, str){ 
    if(typeof str === 'object'){ 
    if(str.length){ 
     var str0 = str.shift(); 
     return objectDive(parent[str0], str); 
    }else{ 
     return parent; 
    } 
    }else{ 
    if(typeof str === 'string'){ 
     return objectDive(parent,str.split('.')); 
    } 
    } 
} 
0

Ora, questo può essere eccessivo per voi, ma qui è una funzione generica che creerà un oggetto con "chiavi multiple". Quello che effettivamente fa è avere una proprietà reale con il valore effettivo, e quindi definisce getter e setter per inoltrare le operazioni dalle chiavi virtuali alla proprietà effettiva.

function multiKey(keyGroups) { 
    let obj = {}; 
    let props = {}; 

    for (let keyGroup of keyGroups) { 
     let masterKey = keyGroup[0]; 
     let prop = { 
      configurable: true, 
      enumerable: false, 

      get() { 
       return obj[masterKey]; 
      }, 

      set(value) { 
       obj[masterKey] = value; 
      } 
     }; 

     obj[masterKey] = undefined; 
     for (let i = 1; i < keyGroup.length; ++i) { 
      if (keyGroup.hasOwnProperty(i)) { 
       props[keyGroup[i]] = prop; 
      } 
     } 
    } 

    return Object.defineProperties(obj, props); 
} 

Questo è meno impreciso quanto ci si aspetterebbe, ha fondamentalmente nessuna penalità prestazioni una volta che l'oggetto viene creato, e si comporta bene con l'enumerazione (for...in loop) e il controllo di appartenenza (in operatore). Ecco alcuni esempio di utilizzo:

let test = multiKey([ 
    ['north', 'up'], 
    ['south', 'down'], 
    ['east', 'left'], 
    ['west', 'right'] 
]); 

test.north = 42; 
test.down = 123; 

test.up; // returns 42 
test.south; // returns 123 

let count = 0; 
for (let key in test) { 
    count += 1; 
} 

count === 4; // true; only unique (un-linked) properties are looped over 

Tratto da my Gist, che si può sborsare.

1

che dovrebbe funzionare come previsto:

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; 
} 
0
//create some objects(!) you want to have aliases for..like tags 
var {learn,image,programming} = 
["learn", "image", "programming"].map(tag=>({toString:()=>tag })); 


//create arbitrary many aliases using a Map 
var alias = new Map(); 
alias.set("photo", image); 
alias.set("pic", image); 
alias.set("learning", learn); 
alias.set("coding", programming); 

//best put the original tagNames in here too.. 
//pretty easy huh? 

// returns the image object 
alias.get("pic"); 

// ;) 
+1

, per favore spiega anche il tuo codice. Solo il codice postale non aiuta OP. – RaghavGarg

2

Un'altra soluzione, se lo può permettere l'esecuzione RegExp, e 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 

vedi Documentazione:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get

+0

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get –

1

Stessa risposta (Proxy ES6, RegExp), ma in un più breve modo (e significativamente meno leggibile)

let align = new Proxy({ 

    'start|top|left': -1, 
    'middle|center': 0, 
    'end|bottom|right': 1, 

}, { get: (t, p) => Object.keys(t).reduce((r, v) => r !== undefined ? r : (new RegExp(v).test(p) ? t[v] : undefined), undefined) }) 

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

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

align.end  // 1 
align.bottom // 1 
align.right  // 1 
Problemi correlati