¿Cómo obtengo los últimos cuatro caracteres de una cadena en C #?

309

Supongamos que tengo una cadena:

"34234234d124"

Quiero obtener los últimos cuatro caracteres de esta cadena que es "d124". Puedo usar SubString, pero necesita un par de líneas de código, incluido el nombramiento de una variable.

¿Es posible obtener este resultado en una expresión con C #?

KentZhou
fuente
3
¿Qué quieres cuando hay menos de 4 caracteres?
agent-j
12
4 > mystring.length ? mystring : mystring.Substring(mystring.length -4);
Jodrell
3
En Python la solución es simple: "hello world"[-4:]. Espero que una versión futura de C # lo haga tan fácil.
Coronel Panic
@ColonelPanic, ahora puedes hacerlo con C # 8.0: "hello world"[^4..]:-)
Frode Evensen

Respuestas:

407
mystring.Substring(Math.Max(0, mystring.Length - 4)); //how many lines is this?

Si está seguro de que la longitud de su cadena es de al menos 4, entonces es aún más corta:

mystring.Substring(mystring.Length - 4);
Armen Tsirunyan
fuente
13
Además, fallará si mystringtiene menos de 4 caracteres de longitud.
George Duckett
3
+1 porque creo que el tuyo es un poco más legible que @ dtb's
George Duckett
Tomar un par de líneas de código (que el OP ya sabía) y agruparlo en una línea no es realmente lo mismo que una expresión.
Buh Buh
1
Me gusta. Simple y elegante y toma el máximo, por lo que si su cadena es inferior a 0 no obtendrá una excepción de índice.
Bretticus
+1 simple y al grano, cubre todas las bases. El método de extensión propuesto por Stecya también es bueno, pero un poco exagerado si solo lo haces una vez.
Morvael
205

Puedes usar un método de extensión :

public static class StringExtension
{
    public static string GetLast(this string source, int tail_length)
    {
       if(tail_length >= source.Length)
          return source;
       return source.Substring(source.Length - tail_length);
    }
}

Y luego llame:

string mystring = "34234234d124";
string res = mystring.GetLast(4);
Stecya
fuente
11
Me gusta esto, pero probablemente solo lo llamaría Last (). Después de todo, Substring () no es GetSubstring ().
Buh Buh
21
Quizás lo llame Tail () como Últimos enfrentamientos con la Extensión de Linq Last ().
Craig Curtis
55
+1 por hacerlo "mucho más largo que 1 línea". Es muy molesto ver código ilegible debido al ahorro de línea.
Fabio Milheiro
2
O llámelo Right () por coherencia con VisualBasic según la respuesta de @RJ Programmer (no quiero agregar otro ensamblaje solo para una función).
christutty
3
Amo esta solución
Lucas
46

Todo lo que tienes que hacer es..

String result = mystring.Substring(mystring.Length - 4);
la estrella
fuente
2
No si quieres que se lance una excepción si la longitud es menor a 4 ...
Milos Mrdovic
45

Ok, entonces veo que esta es una publicación antigua, pero ¿por qué estamos reescribiendo el código que ya se proporciona en el marco?

Sugeriría que agregue una referencia a la DLL del marco "Microsoft.VisualBasic"

using Microsoft.VisualBasic;
//...

string value = Strings.Right("34234234d124", 4);
Programador RJ
fuente
8
Buen ejemplo de un momento para usar la funcionalidad VB
Brian White
3
te quiero. La mayor parte de mi experiencia en programación es VB, así que descubrir que puedo usar todas esas funciones con las que estoy tan familiarizado es increíble
Ben Strombeck, el
66
Nunca puedo entender si usar MS.VB es una buena idea: ¿por qué se deriva al VisualBasicespacio de nombres? TextFieldParserEs otro ejemplo. ¿Por qué estas utilidades tienen un factor tan extraño?
ruffin
66
Siento que esta debería ser la respuesta aceptada. ¿Por qué reinventar la rueda?
Zack
2
@Bomboca: Podemos estar seguros de que continuará mientras Microsoft continúe admitiendo Visual Basic. Se incluye en la versión 4.6 y no puedo encontrar nada explícito o implícito de MS que planeen dejar de admitir VB.Net como lenguaje de desarrollo.
Programador RJ
30
string mystring = "34234234d124";
mystring = mystring.Substring(mystring.Length-4)
Cem
fuente
26

Usar Substring es en realidad bastante corto y legible:

 var result = mystring.Substring(mystring.Length - Math.Min(4, mystring.Length));
 // result == "d124"
dtb
fuente
17

Aquí hay otra alternativa que no debería funcionar demasiado mal (debido a la ejecución diferida ):

new string(mystring.Reverse().Take(4).Reverse().ToArray());

Aunque un método de extensión para este propósito mystring.Last(4)es claramente la solución más limpia, aunque un poco más de trabajo.

Andre Luus
fuente
1
@BrianWhite ¿La gente está irritable después del año nuevo?
Konrad Viltersten
1
Buena solución me gusta. Pero olvidaste otro reverso para obtener la cadena correcta. Debe ser: nueva cadena (mystring.Reverse (). Take (4) .Reverse (). ToArray ());
Yuri Morales
Ah, sí, tienes razón: mi compilador mental no pensaba tanto. ¡Lamentablemente eso lo hace parecer aún peor! :)
Andre Luus
1
Debido a ToArray no hay ejecución diferida
1
No creo que entiendas, @ BjörnAliGöransson, mi punto era que Reverse().Take(4).Reverse()no enumeraban toda la cadena, solo sucede en la ToArrayllamada final . Si no hubiera tal cosa como ejecución diferida, se traduciría a Reverse().ToArray().Take(4).ToArray().Reverse().ToArray(). Esto, por supuesto, supone que esas extensiones son del tipo diferido, lo cual no verifiqué. Los constructores de cadenas no aceptan IEnumerable, por lo que debe enumerarlo en una matriz en ese punto.
Andre Luus
17

Simplemente puede usar el Substringmétodo de C #. Por ej.

string str = "1110000";
string lastFourDigits = str.Substring((str.Length - 4), 4);

Devolverá el resultado 0000.

Amit Kumawat
fuente
77
Esto ha sido respondido como 28 veces y lo agregaste nuevamente? ¿Y por qué usar la sobrecarga de dos parámetros en lugar de la que solo recibe startIndex?
Andrew
Exactamente la respuesta que necesitaba. Gracias por compartir @Amit Kumawat.
Daryl
12

Una solución simple sería:

string mystring = "34234234d124";
string last4 = mystring.Substring(mystring.Length - 4, 4);
Anees Deen
fuente
7
mystring = mystring.Length > 4 ? mystring.Substring(mystring.Length - 4, 4) : mystring;
Michael Burggraf
fuente
Bien, pero creo que querías decir que =no =+.
dotancohen
1
mystring.Substring (mystring.Length - 4, 4) es lo mismo que: mystring.Substring (mystring.Length - 4)
Moe Howard
6

Es solo esto:

int count = 4;
string sub = mystring.Substring(mystring.Length - count, count);
Daniel DiPaolo
fuente
6

En comparación con algunas respuestas anteriores, la principal diferencia es que este código tiene en cuenta cuando la cadena de entrada es:

  1. Nulo
  2. Más largo o que coincida con la longitud solicitada
  3. Más corta que la longitud solicitada.

Aquí está:

public static class StringExtensions
{
    public static string Right(this string str, int length)
    {
        return str.Substring(str.Length - length, length);
    }

    public static string MyLast(this string str, int length)
    {
        if (str == null)
            return null;
        else if (str.Length >= length)
            return str.Substring(str.Length - length, length);
        else
            return str;
    }
}
Marcelo Finki
fuente
4

Definición:

public static string GetLast(string source, int last)
{
     return last >= source.Length ? source : source.Substring(source.Length - last);
}

Uso:

GetLast("string of", 2);

Resultado:

de

Erçin Dedeoğlu
fuente
3

Esto no fallará para cualquier cadena de longitud.

string mystring = "34234234d124";
string last4 = Regex.Match(mystring, "(?!.{5}).*").Value;
// last4 = "d124"
last4 = Regex.Match("d12", "(?!.{5}).*").Value;
// last4 = "d12"

Probablemente esto sea excesivo para la tarea en cuestión, pero si necesita una validación adicional, posiblemente se pueda agregar a la expresión regular.

Editar: creo que esta expresión regular sería más eficiente:

@".{4}\Z"
agente-j
fuente
55
Definitivamente exagerado. Me quedaría con métodos de cadena simples para esto.
tsells
¡La segunda variante no devuelve una cadena de tres letras cuando se llama con un argumento de tres letras, por lo que no es equivalente a su primera versión ingeniosa que usa anticipación negativa! :-)
avl_sweden
3

Utiliza un genérico Last<T>. Eso funcionará con CUALQUIERA IEnumerable, incluida la cadena.

public static IEnumerable<T> Last<T>(this IEnumerable<T> enumerable, int nLastElements)
{
    int count = Math.Min(enumerable.Count(), nLastElements);
    for (int i = enumerable.Count() - count; i < enumerable.Count(); i++)
    {
        yield return enumerable.ElementAt(i);
    }
}

Y uno específico para cadena:

public static string Right(this string str, int nLastElements)
{
    return new string(str.Last(nLastElements).ToArray());
}
Adriano Carneiro
fuente
1
Guau. Exceso ¿Tal vez algo como enumerable.Skip (enumerable.Count () - nLastElements)?
Buh Buh
No estoy de acuerdo con @BuhBuh sobre esta exageración. Pero prefiero "Apellido" a "Correcto" como nombre. Estoy un poco aprensivo acerca de sobrecargar el Last of IEnumerable <T> existente. También me estoy inclinando hacia "Skip".
Plausiblemente negable
Me gusta esta solución No es simple pero interesante al aprender IEnumerable.
pKarelian
1

Reuní algunos códigos modificados de varias fuentes que obtendrán los resultados que deseas y además harás mucho más. He permitido valores int negativos, valores int que exceden la longitud de la cadena y para que el índice final sea menor que el índice inicial. En ese último caso, el método devuelve una subcadena de orden inverso. Hay muchos comentarios, pero avíseme si algo no está claro o simplemente es una locura. Estaba jugando con esto para ver para qué podría usarlo.

    /// <summary>
    /// Returns characters slices from string between two indexes.
    /// 
    /// If start or end are negative, their indexes will be calculated counting 
    /// back from the end of the source string. 
    /// If the end param is less than the start param, the Slice will return a 
    /// substring in reverse order.
    /// 
    /// <param name="source">String the extension method will operate upon.</param>
    /// <param name="startIndex">Starting index, may be negative.</param>
    /// <param name="endIndex">Ending index, may be negative).</param>
    /// </summary>
    public static string Slice(this string source, int startIndex, int endIndex = int.MaxValue)
    {
        // If startIndex or endIndex exceeds the length of the string they will be set 
        // to zero if negative, or source.Length if positive.
        if (source.ExceedsLength(startIndex)) startIndex = startIndex < 0 ? 0 : source.Length;
        if (source.ExceedsLength(endIndex)) endIndex = endIndex < 0 ? 0 : source.Length;

        // Negative values count back from the end of the source string.
        if (startIndex < 0) startIndex = source.Length + startIndex;
        if (endIndex < 0) endIndex = source.Length + endIndex;         

        // Calculate length of characters to slice from string.
        int length = Math.Abs(endIndex - startIndex);
        // If the endIndex is less than the startIndex, return a reversed substring.
        if (endIndex < startIndex) return source.Substring(endIndex, length).Reverse();

        return source.Substring(startIndex, length);
    }

    /// <summary>
    /// Reverses character order in a string.
    /// </summary>
    /// <param name="source"></param>
    /// <returns>string</returns>
    public static string Reverse(this string source)
    {
        char[] charArray = source.ToCharArray();
        Array.Reverse(charArray);
        return new string(charArray);
    }

    /// <summary>
    /// Verifies that the index is within the range of the string source.
    /// </summary>
    /// <param name="source"></param>
    /// <param name="index"></param>
    /// <returns>bool</returns>
    public static bool ExceedsLength(this string source, int index)
    {
        return Math.Abs(index) > source.Length ? true : false;
    }

Entonces, si tiene una cadena como "Este es un método de extensión", aquí hay algunos ejemplos y resultados que puede esperar.

var s = "This is an extension method";
// If you want to slice off end characters, just supply a negative startIndex value
// but no endIndex value (or an endIndex value >= to the source string length).
Console.WriteLine(s.Slice(-5));
// Returns "ethod".
Console.WriteLine(s.Slice(-5, 10));
// Results in a startIndex of 22 (counting 5 back from the end).
// Since that is greater than the endIndex of 10, the result is reversed.
// Returns "m noisnetxe"
Console.WriteLine(s.Slice(2, 15));
// Returns "is is an exte"

Esperemos que esta versión sea útil para alguien. Funciona de manera normal si no usa números negativos y proporciona valores predeterminados para parámetros fuera de rango.

irlandesa
fuente
1
string var = "12345678";

if (var.Length >= 4)
{
    var = var.substring(var.Length - 4, 4)
}

// result = "5678"
Eidan
fuente
1

suponiendo que desea las cadenas entre una cadena que se encuentra a 10 caracteres del último carácter y necesita solo 3 caracteres.

Digamos StreamSelected = "rtsp://72.142.0.230:80/SMIL-CHAN-273/4CIF-273.stream"

En lo anterior, necesito extraer el "273"que usaré en la consulta de la base de datos

        //find the length of the string            
        int streamLen=StreamSelected.Length;

        //now remove all characters except the last 10 characters
        string streamLessTen = StreamSelected.Remove(0,(streamLen - 10));   

        //extract the 3 characters using substring starting from index 0
        //show Result is a TextBox (txtStreamSubs) with 
        txtStreamSubs.Text = streamLessTen.Substring(0, 3);
Shinn_33
fuente
Esta pregunta pide explícitamente los últimos cuatro caracteres en la cadena. Parece que está respondiendo una pregunta diferente relacionada con la extracción de elementos del medio de la cadena. También Substringya te permite pasar un punto de inicio y una longitud, así que no estoy seguro de por qué no usarías eso en lugar de usarlo Removepara eliminar el principio primero.
Chris
0

La actualización 2020 : C # 8.0 finalmente lo hace fácil:

> "C# 8.0 finally makes this easy"[^4..]
"easy"

También puede dividir matrices de la misma manera, ver Índices y rangos .

Coronel Panic
fuente