@TotZam - por favor verifique las fechas. Este es más antiguo que el que vinculaste.
ToolmakerSteve
@ToolmakerSteve Generalmente miro la calidad de la pregunta y las respuestas, no las fechas, como se dice aquí . En este caso, parece que he cometido un error y he hecho clic en el incorrecto para marcarlo como duplicado, ya que la calidad de esta pregunta es obviamente mejor, por lo que he marcado la otra pregunta.
Tot Zam
@TotZam - ah, no sabía sobre esa recomendación - gracias por señalarlo. (Aunque es confuso ver que algo antiguo se informa como un duplicado de algo más nuevo, por lo que en tal caso, valdría la pena explicar explícitamente que está marcando como duplicado una pregunta ANTERIOR, porque la vinculada tiene mejores respuestas).
ToolmakerSteve
Respuestas:
198
La forma más fácil de agregar y eliminar rangos en una cadena es usar el StringBuilder.
var theString ="ABCDEFGHIJ";var aStringBuilder =newStringBuilder(theString);
aStringBuilder.Remove(3,2);
aStringBuilder.Insert(3,"ZX");
theString = aStringBuilder.ToString();
Una alternativa es usarla String.Substring, pero creo que el StringBuildercódigo se vuelve más legible.
sería mejor concluir eso en un método de extensión :)
balexandre
¿Por qué usas un StringBuilder aquí? Verifique la respuesta de V4Vendetta, que es mucho más legible ...
Fortega
1
@Fortega Remove () e Insert () crean y devuelven una nueva cadena. El enfoque StringBuilder evita este costo adicional trabajando dentro de una sección de memoria preasignada y moviendo caracteres dentro de ella.
redcalx
@redcalx Eso es cierto, pero se introduce un costo adicional al introducir un objeto StringBuilder y al reducir la legibilidad
Fortega
2
¿Cuál es el punto de usar StringBuilder aquí, si está llamando Eliminar e Insertar de la misma manera que V4Vendetta, pero lo está haciendo directamente en la cadena? Parece código redundante.
metabuddy
186
string s ="ABCDEFGH";
s= s.Remove(3,2).Insert(3,"ZX");
Prefiero esto sobre inicializar un nuevo StringBuilder (...). ¡Gracias!
Michael Norgren
3
No sé por qué alguien usaría stringbuilder para esta operación. Esta es una buena respuesta
NappingRabbit
43
ReplaceAt (int index, int length, string replace)
Aquí hay un método de extensión que no usa StringBuilder o Substring. Este método también permite que la cadena de reemplazo se extienda más allá de la longitud de la cadena de origen.
//// str - the source string//// index- the start location to replace at (0-based)//// length - the number of characters to be removed before inserting//// replace - the string that is replacing characterspublicstaticstringReplaceAt(thisstring str,int index,int length,string replace){return str.Remove(index,Math.Min(length, str.Length- index)).Insert(index, replace);}
Cuando utilice esta función, si desea que toda la cadena de reemplazo reemplace tantos caracteres como sea posible, configure la longitud a la longitud de la cadena de reemplazo:
Supongo que esto es más eficiente ya que la clase StringBuilder no necesita inicializarse y ya que usa operaciones más básicas. Por favor, corríjame si estoy equivocado. :)
Stringbuilder es más eficiente si la cadena es más larga que, digamos 200 caracteres.
Tim Schmelter
Sin estrés. Trabajado derecho. Gracias
D_Edet
9
Use String.Substring()(detalles aquí ) para cortar la parte izquierda, luego su reemplazo, luego la parte derecha. Juega con índices hasta que lo hagas bien :)
Creé tres métodos usando los tres métodos anteriores (string.Remove / Insert, Stringbuilder.Remove / Insert y Daniel's Substring answer, y SubString fue el método más rápido.
Esto funciona, probablemente no quieras volver a ponerlo de tnuevo.
Pierre
4
Si le importa el rendimiento, lo que quiere evitar aquí son las asignaciones. Y si está utilizando .Net Core 2.1+ (o, aún no publicado, .Net Standard 2.1), puede hacerlo utilizando el string.Createmétodo :
Todas las demás respuestas no funcionan si la cadena contiene caracteres Unicode (como Emojis) porque un carácter Unicode pesa más bytes que un carácter.
Ejemplo : el emoji '🎶' convertido a bytes, pesará el equivalente a 2 caracteres. Entonces, si el carácter unicode se coloca al comienzo de su cadena, el offsetparámetro se desplazará).
Con este tema , extiendo la clase StringInfo a Reemplazar por posición manteniendo el algoritmo de Nick Miller para evitar eso:
dotnetfiddle.net/l0dqS5 No pude hacer que otros métodos fallaran en Unicode. Modifique el violín para demostrar su caso de uso. Muy interesado, en resultados.
Markus
1
@ MarkusHooge Intente colocar los caracteres unicode al comienzo de su cadena como: dotnetfiddle.net/3V2K3Y . Verá que solo la última línea funciona bien y colocará el carácter en el cuarto lugar (en el otro caso, el carácter unicode tiene una longitud de 2 caracteres)
GGO
Tienes razón, no está claro. Actualicé mi respuesta para agregar más explicaciones de por qué la respuesta de los demás no funciona
GGO
1
Estaba buscando una solución con los siguientes requisitos:
use solo una expresión de una línea
use solo métodos incorporados al sistema (ninguna utilidad implementada personalizada)
Solución 1
La solución que mejor me conviene es esta:
// replace `oldString[i]` with `c`string newString =newStringBuilder(oldString).Replace(oldString[i], c, i,1).ToString();
La otra solución que satisface mis requisitos es usar Substring con concatenación:
string newString = oldStr.Substring(0, i)+ c + oldString.Substring(i+1, oldString.Length);
Esto también está bien. me conjetura que no es tan eficiente como la primera actuación sabia (debido a la concatenación de cadenas innecesario). Pero la optimización prematura es la raíz de todo mal .
La solución 2 funciona pero requiere corrección: string newString = oldStr.Substring (0, i) + c + oldString.Substring (i + 1, oldString.Length- (i + 1));
Déjame explicarte mi solución.
Dado el enunciado del problema de alterar una cadena en sus dos posiciones específicas (“posición 4 a posición 5”) con dos caracteres 'Z' y 'X' y la pregunta es usar el índice de posición para alterar la cadena y no la cadena Reemplazar ( ) método (puede deberse a la posibilidad de repetición de algunos caracteres en la cadena real), preferiría utilizar un enfoque minimalista para lograr el objetivo sobre el uso de Substring()y cadena Concat()o cadena Remove()y Insert()enfoque. Aunque todas esas soluciones servirán para lograr el mismo objetivo, pero solo depende de la elección personal y la filosofía de resolver con un enfoque minimalista.
Volviendo a la solución mencionada anteriormente, si miramos más de cercastring yStringBuilder, ambos tratan internamente una cadena dada como una matriz de caracteres. Si observamos su implementación StringBuilder, mantiene una variable interna algo así como " internal char[] m_ChunkChars;" para capturar la cadena dada. Ahora, dado que esta es una variable interna, no podemos acceder directamente a la misma. Para el mundo externo, para poder acceder y modificar esa matriz de caracteres, los StringBuilderexpone a través de la propiedad del indexador que se parece a continuación
[IndexerName("Chars")]publiccharthis[int index]{get{StringBuilder stringBuilder =this;do{// … some codereturn stringBuilder.m_ChunkChars[index1];// … some more code}}set{StringBuilder stringBuilder =this;do{//… some code
stringBuilder.m_ChunkChars[index1]=value;return;// …. Some more code}}}
Mi solución mencionada anteriormente aprovecha esta capacidad de indexador para alterar directamente la matriz de caracteres mantenida internamente, que IMO es eficiente y minimalista.
Por cierto; podemos reescribir la solución anterior de manera más elaborada, algo como a continuación
En este contexto, también me gustaría mencionar que en caso de stringque también tenga una propiedad de indexador como un medio para exponer su matriz de caracteres interna, pero en este caso solo tiene la propiedad Getter (y no Setter) ya que la cadena es inmutable por naturaleza. Y es por eso que necesitamos usar StringBuilderpara alterar la matriz de caracteres.
Y por último, pero no menos importante, esta solución solo se ajusta mejor a este problema específico en el que la solicitud es reemplazar solo unos pocos caracteres con un índice de posición conocido por adelantado. Es posible que no sea la mejor opción cuando el requisito es alterar una cadena bastante larga, es decir, el número de caracteres a modificar es grande en números.
Creo que la forma más simple sería esta: (sin stringbuilder)
string myString ="ABCDEFGHIJ";char[] replacementChars ={'Z','X'};byte j =0;for(byte i =3; i <=4; i++, j++){
myString = myString.Replace(myString[i], replacementChars[j]);}
Esto funciona porque una variable de tipo cadena se puede tratar como una matriz de variables char. Puede, por ejemplo, referirse al segundo carácter de una variable de cadena con el nombre "myString" como myString [1]
Esto solo funciona porque, en el ejemplo del autor, stringlos caracteres a ser reemplazados aparecen una sola vez. Si ejecuta esto contra, digamos, "DBCDEFGHIE"entonces obtiene "ZBCZXFGHIX", que no es el resultado deseado. Además, no estaría de acuerdo en que esto sea más simple que las otras StringBuildersoluciones que se publicaron hace dos años y medio.
Respuestas:
La forma más fácil de agregar y eliminar rangos en una cadena es usar el
StringBuilder
.Una alternativa es usarla
String.Substring
, pero creo que elStringBuilder
código se vuelve más legible.fuente
fuente
ReplaceAt (int index, int length, string replace)
Aquí hay un método de extensión que no usa StringBuilder o Substring. Este método también permite que la cadena de reemplazo se extienda más allá de la longitud de la cadena de origen.
Cuando utilice esta función, si desea que toda la cadena de reemplazo reemplace tantos caracteres como sea posible, configure la longitud a la longitud de la cadena de reemplazo:
De lo contrario, puede especificar la cantidad de caracteres que se eliminarán:
Si especifica que la longitud sea 0, esta función actúa igual que la función de inserción:
Supongo que esto es más eficiente ya que la clase StringBuilder no necesita inicializarse y ya que usa operaciones más básicas. Por favor, corríjame si estoy equivocado. :)
fuente
Use
String.Substring()
(detalles aquí ) para cortar la parte izquierda, luego su reemplazo, luego la parte derecha. Juega con índices hasta que lo hagas bien :)Algo como:
fuente
Como un método de extensión.
fuente
fuente
t
nuevo.Si le importa el rendimiento, lo que quiere evitar aquí son las asignaciones. Y si está utilizando .Net Core 2.1+ (o, aún no publicado, .Net Standard 2.1), puede hacerlo utilizando el
string.Create
método :Este enfoque es más difícil de entender que las alternativas, pero es el único que asignará solo un objeto por llamada: la cadena recién creada.
fuente
Podría intentar algo enlazar esto:
fuente
Como otros han mencionado, la
Substring()
función está ahí por una razón:También calculé esto contra la
StringBuilder
solución y obtuve 900 tics frente a 875. Por lo tanto, es un poco más lento.fuente
"ABCDEFGHIJ"
y"ZX"
son de diferentes longitudes.Aún otra
fuente
Con la ayuda de esta publicación, creo la siguiente función con verificaciones de longitud adicionales
fuente
Todas las demás respuestas no funcionan si la cadena contiene caracteres Unicode (como Emojis) porque un carácter Unicode pesa más bytes que un carácter.
Con este tema , extiendo la clase StringInfo a Reemplazar por posición manteniendo el algoritmo de Nick Miller para evitar eso:
fuente
Estaba buscando una solución con los siguientes requisitos:
Solución 1
La solución que mejor me conviene es esta:
Esto usa
StringBuilder.Replace(oldChar, newChar, position, count)
Solución 2
La otra solución que satisface mis requisitos es usar
Substring
con concatenación:Esto también está bien. me conjetura que no es tan eficiente como la primera actuación sabia (debido a la concatenación de cadenas innecesario). Pero la optimización prematura es la raíz de todo mal .
Así que elige el que más te guste :)
fuente
Es mejor usar el
String.substr()
.Me gusta esto:
fuente
Déjame explicarte mi solución.
Dado el enunciado del problema de alterar una cadena en sus dos posiciones específicas (“posición 4 a posición 5”) con dos caracteres 'Z' y 'X' y la pregunta es usar el índice de posición para alterar la cadena y no la cadena Reemplazar ( ) método (puede deberse a la posibilidad de repetición de algunos caracteres en la cadena real), preferiría utilizar un enfoque minimalista para lograr el objetivo sobre el uso de
Substring()
y cadenaConcat()
o cadenaRemove()
yInsert()
enfoque. Aunque todas esas soluciones servirán para lograr el mismo objetivo, pero solo depende de la elección personal y la filosofía de resolver con un enfoque minimalista.Volviendo a la solución mencionada anteriormente, si miramos más de cerca
string
yStringBuilder
, ambos tratan internamente una cadena dada como una matriz de caracteres. Si observamos su implementaciónStringBuilder
, mantiene una variable interna algo así como "internal char[] m_ChunkChars;
" para capturar la cadena dada. Ahora, dado que esta es una variable interna, no podemos acceder directamente a la misma. Para el mundo externo, para poder acceder y modificar esa matriz de caracteres, losStringBuilder
expone a través de la propiedad del indexador que se parece a continuaciónMi solución mencionada anteriormente aprovecha esta capacidad de indexador para alterar directamente la matriz de caracteres mantenida internamente, que IMO es eficiente y minimalista.
Por cierto; podemos reescribir la solución anterior de manera más elaborada, algo como a continuación
En este contexto, también me gustaría mencionar que en caso de
string
que también tenga una propiedad de indexador como un medio para exponer su matriz de caracteres interna, pero en este caso solo tiene la propiedad Getter (y no Setter) ya que la cadena es inmutable por naturaleza. Y es por eso que necesitamos usarStringBuilder
para alterar la matriz de caracteres.Y por último, pero no menos importante, esta solución solo se ajusta mejor a este problema específico en el que la solicitud es reemplazar solo unos pocos caracteres con un índice de posición conocido por adelantado. Es posible que no sea la mejor opción cuando el requisito es alterar una cadena bastante larga, es decir, el número de caracteres a modificar es grande en números.
fuente
fuente
Aquí hay un método de extensión simple:
Úselo así:
fuente
Creo que la forma más simple sería esta: (sin stringbuilder)
Esto funciona porque una variable de tipo cadena se puede tratar como una matriz de variables char. Puede, por ejemplo, referirse al segundo carácter de una variable de cadena con el nombre "myString" como myString [1]
fuente
string
los caracteres a ser reemplazados aparecen una sola vez. Si ejecuta esto contra, digamos,"DBCDEFGHIE"
entonces obtiene"ZBCZXFGHIX"
, que no es el resultado deseado. Además, no estaría de acuerdo en que esto sea más simple que las otrasStringBuilder
soluciones que se publicaron hace dos años y medio.