Jak uzyskać ostatnie cztery znaki z ciągu w C #?


309

Załóżmy, że mam ciąg:

"34234234d124"

Chcę uzyskać cztery ostatnie znaki tego ciągu, który jest "d124". Mogę użyć SubString, ale potrzebuje kilku wierszy kodu, w tym nazewnictwa zmiennej.

Czy można uzyskać ten wynik w jednym wyrażeniu za pomocą C #?


3
Czego chcesz, gdy jest mniej niż 4 znaki?
agent-j

12
4 > mystring.length ? mystring : mystring.Substring(mystring.length -4);
Jodrell

3
W Pythonie rozwiązanie jest proste: "hello world"[-4:]. Mam nadzieję, że przyszła wersja C # ułatwi to zadanie.
Pułkownik Panic

@ColonelPanic, teraz możesz z C # 8.0: "hello world"[^4..]:-)
Frode Evensen

Odpowiedzi:


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

Jeśli masz pewność, że długość łańcucha wynosi co najmniej 4, oznacza to, że jest jeszcze krótszy:

mystring.Substring(mystring.Length - 4);

13
Ponadto zawiedzie, jeśli mystringma mniej niż 4 znaki.
George Duckett,

3
+1, ponieważ myślę, że twój jest nieco bardziej czytelny niż @ dtb użytkownika
George Duckett

Wzięcie kilku linii kodu (które OP już wiedział) i wrzucenie go do jednej linii nie jest tak naprawdę tym samym wyrażeniem.
Buh Buh,

1
Lubię to. Prosty i elegancki i zajmuje maksimum, więc jeśli Twój ciąg jest mniejszy niż 0, nie otrzymasz wyjątku poza indeksem.
Bretticus

+1 prosty i do rzeczy, obejmuje wszystkie bazy. Metoda rozszerzenia zaproponowana przez Stecyę jest również dobra, ale trochę za mało, jeśli robisz to tylko raz.
Morvael,

205

Możesz użyć metody rozszerzenia :

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);
    }
}

A potem zadzwoń:

string mystring = "34234234d124";
string res = mystring.GetLast(4);

11
Podoba mi się, ale prawdopodobnie nazwałbym to Last (). W końcu Substring () nie jest GetSubstring ().
Buh Buh,

21
Może nazwać to Tail () jako Last koliduje z Linq Extension Last ().
Craig Curtis

5
+1 za uczynienie go „dużo dłuższym niż 1 linia”. To bardzo denerwujące, aby zobaczyć nieczytelny kod z powodu oszczędności linii.
Fabio Milheiro,

2
Lub nazwij to Right (), aby zachować spójność z VisualBasic zgodnie z odpowiedzią @RJ Programmer (nie chcę dodawać innego zestawu tylko dla jednej funkcji).
christutty,

3
Uwielbiam to rozwiązanie.
Łukasz

46

Wszystko co musisz zrobić to..

String result = mystring.Substring(mystring.Length - 4);

2
Nie, jeśli chcesz, aby wyjątek został
zgłoszony,

45

Ok, więc widzę, że to stary post, ale dlaczego przepisujemy kod, który jest już udostępniony w frameworku?

Sugerowałbym dodanie odniesienia do biblioteki DLL środowiska „Microsoft.VisualBasic”

using Microsoft.VisualBasic;
//...

string value = Strings.Right("34234234d124", 4);

8
Miły przykład użycia funkcji VB
Brian White

3
Kocham Cię. Większość mojego doświadczenia w programowaniu to VB, więc odkrycie, że mogę korzystać ze wszystkich tych funkcji, które znam, jest niesamowite
Ben Strombeck

6
Nigdy nie mogę się dowiedzieć, czy używanie MS.VB jest dobrym pomysłem - dlaczego jest umieszczane w VisualBasicprzestrzeni nazw? TextFieldParserto kolejny przykład. Dlaczego te narzędzia są tak dziwnie faktorowane?
ruffin

6
Wydaje mi się, że to powinna być zaakceptowana odpowiedź. Po co ponownie wymyślać koło?
Zack

2
@Bomboca: Możemy być pewni, że będzie on działał tak długo, jak Microsoft będzie obsługiwał Visual Basic. Jest on zawarty w wersji 4.6 i nie mogę znaleźć niczego jawnego ani sugerowanego przez MS, że planują przestać wspierać VB.Net jako język programowania.
Programator RJ

30
string mystring = "34234234d124";
mystring = mystring.Substring(mystring.Length-4)

26

Korzystanie z podciągów jest w rzeczywistości dość krótkie i czytelne:

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

17

Oto kolejna alternatywa, która nie powinna działać zbyt źle (z powodu odroczonego wykonania ):

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

Chociaż metoda rozszerzenia w tym celu mystring.Last(4)jest zdecydowanie najczystszym rozwiązaniem, choć trochę więcej pracy.


1
@BrianWhite Ludzie są szaleni po nowym roku?
Konrad Viltersten

1
Niezłe rozwiązanie. lubię to. Ale zapomniałeś innego rewersu, aby uzyskać prawidłowy ciąg. Musi być: nowy ciąg znaków (mystring.Reverse (). Take (4) .Reverse (). ToArray ());
Yuri Morales

Ach tak, masz rację - mój kompilator mentalny nie pomyślał aż tak daleko. Niestety, to sprawia, że ​​wydaje się jeszcze gorzej! :)
Andre Luus

1
Z powodu ToArray nie ma odroczonego wykonania

1
Nie wydaje mi się, żebyś rozumiał, @ BjörnAliGöransson, chodziło mi o to, że Reverse().Take(4).Reverse()nie wyliczaj całego łańcucha, dzieje się to tylko przy ostatnim ToArraywywołaniu. Gdyby nie było czegoś takiego jak odroczona egzekucja, przekładałoby się to na Reverse().ToArray().Take(4).ToArray().Reverse().ToArray(). To oczywiście zakłada, że ​​te rozszerzenia są typu odroczonego - którego nie sprawdziłem. Konstruktory String nie akceptują IEnumerable, więc musisz wyliczyć go do tablicy w tym momencie.
Andre Luus,

17

Możesz po prostu użyć Substringmetody C #. Np.

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

Zwróci wynik 0000.


7
Odpowiedzi udzielono 28 razy i dodałeś ją ponownie? I po co używać przeciążenia dwoma parametrami zamiast tego, który tylko otrzymuje startIndex?
Andrew

Właśnie takiej odpowiedzi potrzebowałem. Dzięki za udostępnienie @Amit Kumawat.
Daryl

12

Prostym rozwiązaniem byłoby:

string mystring = "34234234d124";
string last4 = mystring.Substring(mystring.Length - 4, 4);

7
mystring = mystring.Length > 4 ? mystring.Substring(mystring.Length - 4, 4) : mystring;

Ładne, ale myślę, że chodziło =nie =+.
dotancohen,

1
mystring.Substring (mystring.Length - 4, 4) jest taki sam jak: mystring.Substring (mystring.Length - 4)
Moe Howard

6

Po prostu to:

int count = 4;
string sub = mystring.Substring(mystring.Length - count, count);

6

W porównaniu z niektórymi poprzednimi odpowiedziami główna różnica polega na tym, że ten fragment kodu bierze pod uwagę, gdy ciąg wejściowy to:

  1. Zero
  2. Dłuższa lub zgodna z żądaną długością
  3. Krótszy niż żądana długość.

Oto on:

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;
    }
}

4

Definicja:

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

Stosowanie:

GetLast("string of", 2);

Wynik:

z


3

To nie zawiedzie dla żadnego ciągu długości.

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

Prawdopodobnie jest to nadmiar dla danego zadania, ale jeśli zachodzi potrzeba dodatkowej weryfikacji, może zostać dodany do wyrażenia regularnego.

Edycja: Myślę, że to wyrażenie regularne byłoby bardziej wydajne:

@".{4}\Z"

5
Zdecydowanie przesada. Trzymałbym się przy tym prostych metod łańcuchowych.
sprzedaje

Drugi wariant nie zwraca trzyliterowego ciągu, gdy jest wywoływany z trzyliterowym argumentem, więc nie jest równoważny z twoją pierwszą genialną wersją z negatywnym spojrzeniem w przód! :-)
avl_sweden

3

Użyj ogólnego Last<T>. To będzie działać z DOWOLNYM IEnumerable, w tym ciągiem.

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);
    }
}

I konkretny dla łańcucha:

public static string Right(this string str, int nLastElements)
{
    return new string(str.Last(nLastElements).ToArray());
}

1
Łał. Overkill. Może coś takiego jak enumerable.Skip (enumerable.Count () - nLastElements)?
Buh Buh,

Nie zgadzam się z @BuhBuh co do tego, że to przesada. Ale wolę „Last” niż „Right” jako nazwę. Jestem trochę wrażliwy na przeciążenie istniejącego Last of IEnumerable <T>. Niby też skłaniam się ku „Skip”.
Prawdopodobnie niezaprzeczalny

Podoba mi się to rozwiązanie. Nie proste, ale ciekawe podczas nauki IEnumerable.
pKarelian

1

Zrzuciłem razem zmodyfikowany kod z różnych źródeł, który uzyska pożądane wyniki i zrobię znacznie więcej. Dopuszczałem ujemne wartości całkowite, wartości całkowite przekraczające długość łańcucha oraz indeks końcowy mniejszy niż indeks początkowy. W tym ostatnim przypadku metoda zwraca podciąg w kolejności odwrotnej. Jest wiele komentarzy, ale daj mi znać, jeśli coś jest niejasne lub po prostu szalone. Bawiłem się z tym, żeby zobaczyć, do czego wszystkiego mogę go użyć.

    /// <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;
    }

Jeśli więc masz ciąg „To jest metoda rozszerzenia”, oto kilka przykładów i wyników, których możesz się spodziewać.

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"

Mam nadzieję, że ta wersja jest dla kogoś pomocna. Działa tak jak normalnie, jeśli nie używasz żadnych liczb ujemnych, i zapewnia wartości domyślne parametrów spoza zakresu.


1
string var = "12345678";

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

// result = "5678"

1

zakładając, że chcesz łańcuchów pomiędzy łańcuchem, który znajduje się 10 znaków od ostatniego znaku i potrzebujesz tylko 3 znaków.

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

Powyżej muszę wyodrębnić to "273", którego użyję w zapytaniu do bazy danych

        //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);

To pytanie wyraźnie wymaga ostatnich czterech znaków w ciągu. Wygląda na to, że odpowiadasz na inne pytanie związane z wydobywaniem rzeczy ze środka łańcucha. Także Substringjuż pozwala przechodzić w punkcie startowym i długość więc nie wiem, dlaczego nie użyłby że zamiast używać Removedo usuwania początek pierwszego.
Chris

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.