Operaciones comunes de cadenas

Operaciones comunes de cadenas

# Formatear una cadena

Utilice el String.Format() método para reemplazar uno o más elementos en la cadena con la representación de cadena de un objeto específico:

String.Format("Hello {0} Foo {1}", "World", "Bar") //Hello World Foo Bar

# Rellenar una cadena a una longitud fija

string s = "Foo";
string paddedLeft = s.PadLeft(5);        // paddedLeft = "  Foo" (pads with spaces by default)
string paddedRight = s.PadRight(6, '+'); // paddedRight = "Foo+++"
string noPadded = s.PadLeft(2);          // noPadded = "Foo" (original string is never shortened)

# Invertir correctamente una cadena

La mayoría de las veces, cuando las personas tienen que invertir una cadena, lo hacen más o menos así:

char[] a = s.ToCharArray();
System.Array.Reverse(a);
string r = new string(a);

Sin embargo, lo que estas personas no se dan cuenta es que esto es realmente incorrecto.
Y no me refiero a que falta la verificación NULL.

En realidad, es incorrecto porque un Glyph/GraphemeCluster puede constar de varios puntos de código (también conocidos como caracteres).

Para ver por qué esto es así, primero tenemos que ser conscientes del hecho de lo que realmente significa el término "carácter".

Referencia:

Carácter es un término sobrecargado que puede significar muchas cosas.

Un punto de código es la unidad atómica de información. El texto es una secuencia de puntos de código. Cada punto de código es un número al que el estándar Unicode le da significado.

Un grafema es una secuencia de uno o más puntos de código que se muestran como una sola unidad gráfica que un lector reconoce como un elemento único del sistema de escritura. Por ejemplo, tanto a como ä son grafemas, pero pueden constar de múltiples puntos de código (p. ej., ä puede ser dos puntos de código, uno para el carácter base a seguido de uno para la diáresis; pero también hay un único punto de código heredado alternativo que representa este grafema ). Algunos puntos de código nunca forman parte de ningún grafema (p. ej., el no ensamblador de ancho cero o las anulaciones direccionales).

Un glifo es una imagen, normalmente almacenada en una fuente (que es una colección de glifos), que se utiliza para representar grafemas o partes de los mismos. Las fuentes pueden componer varios glifos en una sola representación, por ejemplo, si la ä anterior es un solo punto de código, una fuente puede optar por representarlo como dos glifos separados espacialmente superpuestos. Para OTF, las tablas GSUB y GPOS de la fuente contienen información de sustitución y posicionamiento para que esto funcione. Una fuente también puede contener varios glifos alternativos para el mismo grafema.

Entonces, en C#, un carácter es en realidad un CodePoint.

Lo que significa que si simplemente invierte una cadena válida como Les Misérables , que puede verse así

string s = "Les Mise\u0301rables";

como una secuencia de caracteres, obtendrá:

selbaŕesiM seL

Como puede ver, el acento está en el carácter R, en lugar del carácter e.
Aunque string.reverse.reverse generará la cadena original si invierte ambas veces la matriz de caracteres, este tipo de inversión definitivamente NO es el reverso de la cadena original.

Tendrás que invertir solo cada GraphemeCluster.
Entonces, si se hace correctamente, invierte una cadena como esta:


   private static System.Collections.Generic.List<string> GraphemeClusters(string s)
    {
        System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();

        System.Globalization.TextElementEnumerator enumerator = System.Globalization.StringInfo.GetTextElementEnumerator(s);
        while (enumerator.MoveNext())
        {
            ls.Add((string)enumerator.Current);
        }

        return ls;
    }


    // this 
    private static string ReverseGraphemeClusters(string s)
    {
        if(string.IsNullOrEmpty(s) || s.Length == 1)
             return s;
        
        System.Collections.Generic.List<string> ls = GraphemeClusters(s);
        ls.Reverse();

        return string.Join("", ls.ToArray());
    }

    public static void TestMe()
    {
        string s = "Les Mise\u0301rables";
        // s = "noël";
        string r = ReverseGraphemeClusters(s);

        // This would be wrong:
        // char[] a = s.ToCharArray();
        // System.Array.Reverse(a);
        // string r = new string(a);

        System.Console.WriteLine(r);
    }

Y, oh alegría, te darás cuenta de que si lo haces correctamente de esta manera, también funcionará para los idiomas asiáticos/del sur de Asia/del este de Asia (y francés/sueco/noruego, etc.)...

# Obtener x caracteres del lado derecho de una cadena

Visual Basic tiene funciones Left, Right y Mid que devuelven caracteres de Left, Right y Middle de una cadena. Estos métodos no existen en C#, pero se pueden implementar con Substring() . Se pueden implementar como métodos de extensión como los siguientes:


  public static class StringExtensions
   {
      /// <summary>
      /// VB Left function
      /// </summary>
      /// <param name="stringparam"></param>
      /// <param name="numchars"></param>
      /// <returns>Left-most numchars characters</returns>
      public static string Left( this string stringparam, int numchars )
      {
         // Handle possible Null or numeric stringparam being passed
         stringparam += string.Empty;
    
         // Handle possible negative numchars being passed
         numchars = Math.Abs( numchars );
    
         // Validate numchars parameter        
         if (numchars > stringparam.Length)
            numchars = stringparam.Length;
    
         return stringparam.Substring( 0, numchars );
      }
    
      /// <summary>
      /// VB Right function
      /// </summary>
      /// <param name="stringparam"></param>
      /// <param name="numchars"></param>
      /// <returns>Right-most numchars characters</returns>
      public static string Right( this string stringparam, int numchars )
      {
         // Handle possible Null or numeric stringparam being passed
         stringparam += string.Empty;
    
         // Handle possible negative numchars being passed
         numchars = Math.Abs( numchars );
    
         // Validate numchars parameter        
         if (numchars > stringparam.Length)
            numchars = stringparam.Length;
    
         return stringparam.Substring( stringparam.Length - numchars );
      }
    
      /// <summary>
      /// VB Mid function - to end of string
      /// </summary>
      /// <param name="stringparam"></param>
      /// <param name="startIndex">VB-Style startindex, 1st char startindex = 1</param>
      /// <returns>Balance of string beginning at startindex character</returns>
      public static string Mid( this string stringparam, int startindex )
      {
         // Handle possible Null or numeric stringparam being passed
         stringparam += string.Empty;
    
         // Handle possible negative startindex being passed
         startindex = Math.Abs( startindex );
    
         // Validate numchars parameter        
         if (startindex > stringparam.Length)
            startindex = stringparam.Length;
         
         // C# strings are zero-based, convert passed startindex
         return stringparam.Substring( startindex - 1 );
      }
    
      /// <summary>
      /// VB Mid function - for number of characters
      /// </summary>
      /// <param name="stringparam"></param>
      /// <param name="startIndex">VB-Style startindex, 1st char startindex = 1</param>
      /// <param name="numchars">number of characters to return</param>
      /// <returns>Balance of string beginning at startindex character</returns>
      public static string Mid( this string stringparam, int startindex, int numchars)
      {
         // Handle possible Null or numeric stringparam being passed
         stringparam += string.Empty;
    
         // Handle possible negative startindex being passed
         startindex = Math.Abs( startindex );
    
         // Handle possible negative numchars being passed
         numchars = Math.Abs( numchars );
    
         // Validate numchars parameter        
         if (startindex > stringparam.Length)
            startindex = stringparam.Length;
    
         // C# strings are zero-based, convert passed startindex
         return stringparam.Substring( startindex - 1, numchars );

       }
    }

Este método de extensión se puede utilizar de la siguiente manera:

string myLongString = "Hello World!";
string myShortString = myLongString.Right(6);  // "World!"
string myLeftString = myLongString.Left(5);    // "Hello"
string myMidString1 = myLongString.Left(4);    // "lo World"
string myMidString2 = myLongString.Left(2,3);    // "ell"

# Verificando cadena vacía usando String.IsNullOrEmpty() y String.IsNullOrWhiteSpace()

string nullString = null;
string emptyString = "";
string whitespaceString = "    ";
string tabString = "\t";
string newlineString = "\n";
string nonEmptyString = "abc123";

bool result;

result = String.IsNullOrEmpty(nullString);            // true
result = String.IsNullOrEmpty(emptyString);           // true
result = String.IsNullOrEmpty(whitespaceString);      // false
result = String.IsNullOrEmpty(tabString);             // false
result = String.IsNullOrEmpty(newlineString);         // false
result = String.IsNullOrEmpty(nonEmptyString);        // false

result = String.IsNullOrWhiteSpace(nullString);       // true
result = String.IsNullOrWhiteSpace(emptyString);      // true
result = String.IsNullOrWhiteSpace(tabString);        // true
result = String.IsNullOrWhiteSpace(newlineString);    // true
result = String.IsNullOrWhiteSpace(whitespaceString); // true
result = String.IsNullOrWhiteSpace(nonEmptyString);   // false

# Recortar caracteres no deseados del inicio y/o final de cadenas.

# String.Trim()

string x = "   Hello World!    ";
string y = x.Trim(); // "Hello World!"

string q = "{(Hi!*";
string r = q.Trim( '(', '*', '{' ); // "Hi!"

# String.TrimStart() y String.TrimEnd()

string q = "{(Hi*";
string r = q.TrimStart( '{' ); // "(Hi*"
string s = q.TrimEnd( '*' );   // "{(Hi" 

# Construir una cadena desde Array

El String.Join El método nos ayudará a construir una cadena a partir de una matriz/lista de caracteres o una cadena. Este método acepta dos parámetros. El primero es el delimitador o el separador que te ayudará a separar cada elemento de la matriz. Y el segundo parámetro es el propio Array.

Cadena de char array :

string delimiter=",";
char[] charArray = new[] { 'a', 'b', 'c' };
string inputString = String.Join(delimiter, charArray);

Salida :a,b,c si cambiamos el delimiter como "" entonces la salida será abc .

Cadena de List of char :

string delimiter = "|";
List<char> charList = new List<char>() { 'a', 'b', 'c' };
string inputString = String.Join(delimiter, charList);

Salida :a|b|c

Cadena de List of Strings :

string delimiter = " ";
List<string> stringList = new List<string>() { "Ram", "is", "a","boy" };
string inputString = String.Join(delimiter, stringList);

Salida :Ram is a boy

Cadena de array of strings :

string delimiter = "_";
string[] stringArray = new [] { "Ram", "is", "a","boy" };
string inputString = String.Join(delimiter, stringArray);

Salida :Ram_is_a_boy

# Formateo usando ToString

Usualmente estamos usando String.Format método para fines de formateo, el .ToString generalmente se usa para convertir otros tipos a cadenas. Podemos especificar el formato junto con el método ToString mientras se realiza la conversión, por lo que podemos evitar un formateo adicional. Déjame explicarte cómo funciona con diferentes tipos;

Entero a cadena formateada:

int intValue = 10;
string zeroPaddedInteger = intValue.ToString("000"); // Output will be "010"
string customFormat = intValue.ToString("Input value is 0"); // output will be   "Input value is 10" 

doble a cadena con formato:

double doubleValue = 10.456;
string roundedDouble = doubleValue.ToString("0.00"); // output 10.46
string integerPart = doubleValue.ToString("00");    // output 10
string customFormat = doubleValue.ToString("Input value is 0.0");  // Input value is 10.5

Dar formato a DateTime usando ToString

DateTime currentDate = DateTime.Now; //  {7/21/2016 7:23:15 PM}
string dateTimeString = currentDate.ToString("dd-MM-yyyy HH:mm:ss"); // "21-07-2016 19:23:15"
string dateOnlyString = currentDate.ToString("dd-MM-yyyy"); // "21-07-2016"
string dateWithMonthInWords = currentDate.ToString("dd-MMMM-yyyy HH:mm:ss"); // "21-July-2016 19:23:15"

# Convertir número decimal a formato binario, octal y hexadecimal

  • Para convertir números decimales a formato binario use **base 2**
    Int32 Number = 15;
    Console.WriteLine(Convert.ToString(Number, 2));  //OUTPUT : 1111
    
    
  • Para convertir números decimales a formato octal use **base 8**
    int Number = 15;
    Console.WriteLine(Convert.ToString(Number, 8));  //OUTPUT : 17
    
    
  • Para convertir números decimales a formato hexadecimal, use **base 16**
    var Number = 15;
    Console.WriteLine(Convert.ToString(Number, 16));  //OUTPUT : f
    
    
  • # Dividir una cadena por un carácter específico

    string helloWorld = "hello world, how is it going?";
    string[] parts1 = helloWorld.Split(',');
    
    //parts1: ["hello world", " how is it going?"]
    
    string[] parts2 = helloWorld.Split(' ');
    
    //parts2: ["hello", "world,", "how", "is", "it", "going?"]
    
    

    # Obtener subcadenas de una cadena dada

    string helloWorld = "Hello World!";
    string world = helloWorld.Substring(6); //world = "World!"
    string hello = helloWorld.Substring(0,5); // hello = "Hello"
    
    

    Substring devuelve la cadena desde un índice dado, o entre dos índices (ambos inclusive).

    # Determinar si una cadena comienza con una secuencia dada

    string HelloWorld = "Hello World";
    HelloWorld.StartsWith("Hello"); // true
    HelloWorld.StartsWith("Foo"); // false
    
    

    Encontrar una cadena dentro de una cadena

    Usando el System.String.Contains puede averiguar si existe una cadena en particular dentro de una cadena. El método devuelve un valor booleano, verdadero si la cadena existe o falso.

    string s = "Hello World";
    bool stringExists = s.Contains("ello");  //stringExists =true as the string contains the substring 
    
    

    # Unir una matriz de cadenas en una nueva

    var parts = new[] { "Foo", "Bar", "Fizz", "Buzz"};
    var joined = string.Join(", ", parts);
    
    //joined = "Foo, Bar, Fizz, Buzz"
    
    

    # Obtener un carácter en un índice específico y enumerar la cadena

    Puedes usar el Substring método para obtener cualquier número de caracteres de una cadena en cualquier ubicación dada. Sin embargo, si solo desea un solo carácter, puede usar el indexador de cadenas para obtener un solo carácter en cualquier índice dado como lo hace con una matriz:

    string s = "hello";
    char c = s[1]; //Returns 'e'
    
    

    Observe que el tipo de devolución es char , a diferencia del Substring método que devuelve un string tipo.

    También puede usar el indexador para iterar a través de los caracteres de la cadena:

    string s = "hello";
    foreach (char c in s)
        Console.WriteLine(c);
    /********* This will print each character on a new line:
    h
    e
    l
    l
    o
    **********/
    
    

    # Dividir una cadena por otra cadena

    string str = "this--is--a--complete--sentence";
    string[] tokens = str.Split(new[] { "--" }, StringSplitOptions.None);
    
    

    Resultado:

    [ "esto", "es", "un", "completo", "frase" ]

    # Reemplazar una cadena dentro de una cadena

    Usando el System.String.Replace método, puede reemplazar parte de una cadena con otra cadena.

    string s = "Hello World";
     s = s.Replace("World", "Universe"); // s = "Hello Universe"
    
    

    Se reemplazan todas las apariciones de la cadena de búsqueda.

    Este método también se puede usar para eliminar parte de una cadena, usando el String.Empty campo:

    string s = "Hello World";
    s = s.Replace("ell", String.Empty); // s = "Ho World"
    
    

    # Cambiando el caso de los caracteres dentro de una Cadena

    El System.String La clase admite varios métodos para convertir caracteres en mayúsculas y minúsculas en una cadena.

    • System.String.ToLowerInvariant se utiliza para devolver un objeto String convertido a minúsculas.

    • System.String.ToUpperInvariant se utiliza para devolver un objeto String convertido a mayúsculas.

    Nota: La razón para usar el invariante versiones de estos métodos es evitar la producción de letras específicas de la cultura inesperadas. Esto se explica aquí en detalle.

    Ejemplo:

    string s = "My String";
    s = s.ToLowerInvariant(); // "my string"
    s = s.ToUpperInvariant(); // "MY STRING"
    
    

    Tenga en cuenta que puede elige especificar una Cultura específica al convertir a minúsculas y mayúsculas utilizando los métodos String.ToLower(CultureInfo) y String.ToUpper(CultureInfo) según corresponda.

    # Concatenar una matriz de cadenas en una sola cadena

    El System.String.Join El método permite concatenar todos los elementos en una matriz de cadenas, usando un separador específico entre cada elemento:

    string[] words = {"One", "Two", "Three", "Four"};
    string singleString = String.Join(",", words); // singleString = "One,Two,Three,Four"
    
    

    # Concatenación de cadenas

    La concatenación de cadenas se puede hacer usando el System.String.Concat método, o (mucho más fácil) usando el + operador:

    string first = "Hello ";
    string second = "World";
    
    string concat = first + second; // concat = "Hello World"
    concat = String.Concat(first, second); // concat = "Hello World"
    
    

    En C# 6 esto se puede hacer de la siguiente manera:

    string concat = $"{first},{second}";