2012-03-07 16 views
6

Necesito reemplazar algunas partes de una cadena con C#. Pude encontrar solo una pregunta similar sobre cómo lograr este here pero era PHP.¿Cómo reemplazar dos o más cadenas entre sí?

Mi situación implica un diccionario [cadena, cadena] que contiene pares de sustituir como:

  • perro, gato
  • gato, ratón,
  • ratón, rapaz

Y Tengo una cadena con el valor de:

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

Necesito una función para conseguir esto:

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

Si enumero el diccionario y llame String.Replace por fin, me sale esto:

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

Es raro si esto no se ha hecho antes , (¿Es de conocimiento público?) Pero no pude encontrar ninguno. Entonces lo siento si lo ha hecho y me lo perdí.

+0

Una manera sucia de hacerlo sería usar texto intermedio. Por lo tanto, convierta 'perro' a '1', 'gato' a '2', y luego haga un segundo pase donde convierta '1' y '2' a lo que desea. Asegúrese de usar algo más exclusivo que '1' y '2' (quizás un GUID). Como dije, está sucio, y estoy seguro de que hay una mejor manera. – xbonez

+0

¿Qué es lo que quiere (como salida) para un diccionario {"foo": "1", "bar": "2", "foobar": "3"}, y entrada "foo bar foobarbar"? – Dogbert

+0

@Dogbert "1 2 32" –

Respuesta

9

Así que lo que necesita es para el juego proceso sólo tendrá lugar una vez. ¡Por una vez, creo que la respuesta correcta es en realidad 'use regex'! Aquí hay algo de código:

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" 

El patrón construimos aquí parece (dog|cat|mouse). Cada pieza en esta construcción de alternancia (|) se pasa a través de Regex.Escape, de modo que los caracteres significativos de expresiones regulares en las teclas (como |, ^, etc.) no causan problemas. Cuando se encuentra una coincidencia, el texto coincidente se reemplaza por el valor correspondiente en el diccionario. La cadena solo se escanea una vez, por lo que no hay coincidencia repetida, como es el problema con un iterado string.Replace.

+0

Mejor y más elegante que mis soluciones. +1 de mi parte –

+1

Gracias por su respuesta. Realmente es elegante, pero ya que no tengo experiencia con expresiones regulares; Tengo que preguntar: ¿y si estuviera intentando reemplazar el perro con ca | t? ¿Hay alguna manera de neutralizar las partes que deseo reemplazar (como las barras diagonales inversas y el carácter "|") y evitar crear algo como '(perro | ca | t | mouse)'? –

+0

@ d4wn excelente consideración. He editado el uso de 'Regex.Escape' según sea necesario. – AakashM

1

Lo que quiere es tener todas las sustituciones de cadenas realizadas simultáneamente, para que no obtenga varias sustituciones sobre la misma ficha, ¿verdad?

puedo pensar en dos enfoques, ni particularmente elegantes:

  • iterar sobre su diccionario con el fin específico, por lo que siempre reemplaza ratón/raptor antes de gato/ratón.
  • En lugar de reemplazar cat con 'mouse', reemplázalo con '$ mouse $' o un marcador similar. Esto asegurará que '$ mouse $' no se sustituya por 'raptor' (o, en realidad, '$ raptor $'). Luego, una vez que haya terminado sus cambios, puede eliminar todos los signos '$'.
+0

Para el punto uno necesitaría reemplazar en el orden opuesto de las preguntas, mouse -> raptor luego cat -> mouse y dog ​​-> cat. – TheLukeMcCarthy

+0

En esta muestra específica, sí. Para una solución más general, necesitarías construir algún tipo de gráfico acíclico dirigido para asegurarte. –

+0

es correcto. Solo quería dar un ejemplo concreto para que d4wn pudiera ver por qué no funcionó antes. – TheLukeMcCarthy

Cuestiones relacionadas