2012-03-07 14 views
6

Ho bisogno di sostituire alcune parti di una stringa tra loro usando C#. Potrei trovare solo una domanda simile su come ottenere questo here ma era PHP.Come sostituire due o più stringhe tra loro?

La mia situazione comporta un Dizionario [String, String] che contiene le coppie di sostituire come:

  • cane, gatto
  • gatto, topo,
  • del mouse, raptor

E Ho una stringa con il valore di:

"My dog ate a cat which once ate a mouse got eaten by a raptor" 

Ho bisogno di una funzione per ottenere questo:

"My cat ate a mouse which once ate a raptor got eaten by a raptor" 

Se io enumerare il dizionario e chiamare String.Replace per ordine, ottengo questo:

"My raptor ate a raptor which once ate a raptor got eaten by a raptor" 

E 'strano, se questo non è stato chiesto prima , (È conoscenza comune?) Ma non ho potuto trovare nessuno. Quindi mi dispiace se lo ha e l'ho perso.

+0

Un modo sporco per farlo sarebbe utilizzare un testo intermedio. Quindi, converti 'dog' in '1', 'cat' in '2', e poi fai un secondo passaggio dove converti '1' e '2' in quello che vuoi. Assicurati di utilizzare qualcosa di più unico di "1" e "2" (forse un GUID). Come ho detto, è sporco, e sono sicuro che c'è un modo migliore. – xbonez

+0

Cosa vuoi (come output) per un dizionario {"foo": "1", "bar": "2", "foobar": "3"}, e inserisci "foo bar foobarbar"? – Dogbert

+0

@Dogbert "1 2 32" –

risposta

9

Quindi quello che serve è per il corrispondenza processo abbia luogo solo una volta. Per una volta penso che la risposta giusta sia effettivamente 'usa regex'! Ecco un po 'di codice:

var replacements = new Dictionary<string, string> 
         { 
          { "do|g", "cat" }, 
          { "ca^t", "mouse" }, 
          { "mo$$use", "raptor" } 
         }; 

var source = "My do|g ate a ca^t which once ate a mo$$use"; 

var regexPattern = 
    "(" + 
    string.Join("|", replacements.Keys.Select(Regex.Escape)) + 
    ")"; 

var regex = new Regex(regexPattern); 

var result = regex.Replace(source, match => replacements[match.Value]); 

// Now result == "My cat ate a mouse which once ate a raptor" 

Il modello che costruiamo qui assomiglia (dog|cat|mouse). Ogni pezzo in questa costruzione di alternanzaviene passato attraverso Regex.Escape, in modo che i caratteri significativi delle espressioni regolari nei tasti (come |, ^, ecc.) Non causino problemi. Quando viene trovata una corrispondenza, il testo corrispondente viene sostituito dal valore corrispondente nel dizionario. La stringa viene scansionata una sola volta, quindi non c'è alcuna corrispondenza ripetuta come è il problema con una ripetizione string.Replace.

+0

Meglio e più elegante delle mie soluzioni. +1 da me. –

+1

Grazie per la risposta. È davvero elegante, ma dal momento che non ho esperienza con regex; Devo chiedere: cosa succede se stavo cercando di sostituire il cane con ca | t? C'è un modo per neutralizzare le parti che voglio sostituire (come i backslash e il carattere "|") ed evitare di costruire qualcosa come '(dog | ca | t | mouse)'? –

+0

@ d4wn considerazione eccellente. Ho modificato l'uso di 'Regex.Escape' se necessario. – AakashM

1

Quello che vuoi è avere tutte le sostituzioni di stringa eseguite contemporaneamente, in modo che non si ottengano più sostituzioni sullo stesso token, giusto?

Mi vengono in mente due approcci, né particolarmente elegante:

  • iterare il dizionario in ordine specifico, quindi avrai sempre sostituire il mouse/raptor prima di gatto/topo.
  • Invece di sostituire gatto con "mouse", sostituirlo con "$ mouse $" o un indicatore simile. Ciò assicurerà che "$ mouse $" non venga sostituito da "raptor" (o, in realtà, "$ raptor $"). Quindi, una volta che hai finito i tuoi interruttori, puoi rimuovere tutti i segni '$'.
+0

Per il punto uno dovresti sostituire nell'ordine inverso delle domande, mouse -> raptor poi cat -> mouse quindi cane -> cat. – TheLukeMcCarthy

+0

In questo specifico campione, sì. Per una soluzione più generale, è necessario creare una sorta di grafico aciclico diretto per essere sicuri. –

+0

che è corretto volevo solo dare un esempio concreto in modo che d4wn potesse capire perché non ha funzionato prima. – TheLukeMcCarthy

Problemi correlati