2010-05-22 10 views
7

considerare questo javascript:Javascript Regex per convertire la notazione punto per la notazione staffa

var values = { 
    name: "Joe Smith", 
    location: { 
     city: "Los Angeles", 
     state: "California" 
    } 
} 

var string = "{name} is currently in {location.city}, {location.state}"; 

var out = string.replace(/{([\w\.]+)}/g, function(wholematch,firstmatch) { 
    return typeof values[firstmatch] !== 'undefined' ? 
     values[firstmatch] : wholematch; 
}); 

Ciò produrrà il seguente:

Joe Smith is currently in {location.city}, {location.state} 

ma voglio emettere il seguente:

Joe Smith is currently in Los Angeles, California 

Sto cercando un buon modo per convertire più livelli di notazione punti trovati tra parentesi nella stringa in più parametri da utilizzare con la notazione staffa, in questo modo:

values[first][second][third][etc] 

Essenzialmente, per questo esempio, sto cercando di capire quale stringa e la funzione regex mi avrebbe bisogno di finire con l'equivalente di:

out = values[name] + " is currently in " + values["location"]["city"] + 
    values["location"]["state"]; 

NOTA: Mi piacerebbe farlo senza usare eval().

+0

appena notato un errore di battitura. Ribattezzato 'var joe' a' var values' – Tauren

+0

Un'altra domanda simile ha una soluzione alternativa da @ J-P per le risposte qui. Sembra piuttosto elegante: http://stackoverflow.com/questions/3344392/dynamic-deep-selection-for-a-javascript-object/3344487#3344487 – Tauren

risposta

10

Utilizzando una funzione di supporto per accedere in modo iterativo le proprietà:

function getNestedValue(obj, prop) { 
    var value, props = prop.split('.'); // split property names 

    for (var i = 0; i < props.length; i++) { 
    if (typeof obj != "undefined") { 
     obj = obj[props[i]]; // go next level 
    } 
    } 
    return obj; 
} 

var string = "{name} is currently in {location.city}, {location.state}"; 

var out = string.replace(/{([^}]+)}/g, function(wholematch,firstmatch) { 
    var value = getNestedValue(joe, firstmatch); 
    return typeof value !== 'undefined' ? value : wholematch; 
}); 
// "Joe Smith is currently in Los Angeles, California" 

Prova l'esempio precedente here.

Edit: Qualcosa di un po 'elegante, utilizzando il metodo Array.prototype.reduce, parte del nuovo ECMAScript 5 ° Edizione standard:

function replace(str, obj) { 
    return str.replace(/{([^}]+)}/g, function(wholematch,firstmatch) { 
    var value = firstmatch.split('.').reduce(function (a, b) { 
     return a[b]; 
    }, obj); 
    return typeof value !== 'undefined' ? value : wholematch; 
    }); 
} 

replace("{name} is currently in {location.city}, {location.state}", values); 
// "Joe Smith is currently in Los Angeles, California" 

Prova il nuovo esempio here.

+0

@CMS: bello, che funziona! Tuttavia, non sembra elegante come una soluzione basata su regex e mi piacerebbe credere che ci sia un modo regolare di farlo. Poi di nuovo, forse sarebbe una perdita di tempo per perseguire una soluzione regex. – Tauren

+0

@CMS: la tua espressione regolare non consente nulla tra parentesi graffe? se voglio i valori limite per i nomi di variabile JavaScript validi '[a-zA-Z0-9 _ \.]', Non sarebbe meglio usare '/ {([\ w \.] +)}/G'?In realtà, ciò consentirebbe un periodo all'inizio, che non è permesso, ma è vicino. Oh sì, penso di aver bisogno di includere '$'. – Tauren

+0

@Tauren, giusto è un po 'permissivo, non mi importava troppo, perché quando si accede alle proprietà con la notazione parentesi (o si usano stringhe in un oggetto letterale), non ci sono restrizioni, cioè 'obj [" 3.xx \ u0009 "]' ... – CMS

0

non sono sicuro di come integrare questo in Javascript, ma qui è un frammento Java che utilizza regex per fare la trasformazione è necessario:

String[] tests = { 
     "{name}", 
     "{location.city}", 
     "{location.state.zip.bleh}", 
    }; 
    for (String test : tests) { 
     System.out.println(test.replaceAll("\\{?(\\w+).?", "[$1]")); 
    } 

Questo stampa:

[name] 
[location][city] 
[location][state][zip][bleh] 

Essenzialmente sostituisce tutte le occorrenze di \{?(\w+).? a [$1].

+0

hmm, interessante. Tuttavia, anche se ho ottenuto questo lavoro in JS, penso che finirei con una stringa che avrei bisogno di 'eval', che vorrei evitare. – Tauren

0

È possibile dare un'occhiata all'argomento Error-free deep property access? pubblicato su comp.lang.javascript - questo presenta diversi approcci per fare ciò che si desidera.

Per l'espressione regolare, tutto ciò che serve è /{.*?}/g

Problemi correlati