Wyodrębnij tylko prawą większość n liter z ciągu


110

Jak mogę wyodrębnić jedną, substringktóra składa się z sześciu skrajnych prawych liter z drugiej string?

Np .: mój ciąg to "PER 343573". Teraz chcę tylko wyodrębnić "343573".

W jaki sposób mogę to zrobić?


Możesz użyć kodu źródłowego metody VB.NET Right. Najpierw musisz przekonwertować na C #: referenceource.microsoft.com/#Microsoft.VisualBasic/… Konwertuj na C # za pomocą Converter.telerik.com
Darren Griffith

ale kod VB opiera się na funkcji c # Substring w strings.sc
Our Man in Bananas

To naprawdę nie jest dobry sposób, aby to zrobić, ale jeśli masz problem, możesz dodać odwołanie do Microsoft.VisualBasic.dll i użyć metody Right. Nie jest to metoda rozszerzająca. Musisz go używać w ten sposób:string endOfString = Strings.Right(wholeString, 6);
Alan McBee - MSFT

Odpowiedzi:


156
string SubString = MyString.Substring(MyString.Length-6);

35
To podejście nie działa poprawnie, jeśli ciąg nie jest tak długi, jak wymagana liczba znaków.
stevehipwell

1
W zależności od tego, czego dokładnie chce OP, można również rzucić na to wyrażenia regularne. Jeśli chce tylko cyfry na końcu ciągu, jest to zdecydowanie najbardziej bezbolesne rozwiązanie, zwłaszcza gdy liczba cyfr może się różnić w niektórych późniejszych aktualizacjach oprogramowania.
Joey

2
@Johannes Rössel - Jestem wielkim fanem wyrażeń regularnych (zobacz moje odpowiedzi), ale nigdy nie polecałbym ich w tak prostej sytuacji, jak ta. Wszystkie odpowiedzi, które używają opakowania funkcji, lepiej nadają się do obsługi kodu niż wyrażenie regularne. Najlepszym rozwiązaniem jest metoda rozszerzenia (lub standardowa funkcja w przypadku .NET 2.0).
stevehipwell

@ Stevo3000 - posiadanie rozwiązania, które rzuca, jeśli ciąg ma złą długość, jest prawidłowym rozwiązaniem. Nie jedyne rozwiązanie, ale wciąż.
Marc L.

3
@James - aby być tak samo złośliwym, tylko w tytule wspomniano „n liter”. Rzeczywiste zadane pytanie dotyczyło „prawych sześciu liter” :)
Chris Rogers

69

Napisz metodę rozszerzającą, aby wyrazić Right(n);funkcję. Funkcja powinna radzić sobie z pustymi lub pustymi łańcuchami zwracającymi pusty ciąg, łańcuchami krótszymi niż maksymalna długość zwracającymi oryginalny ciąg i ciągami dłuższymi niż maksymalna długość zwracającymi maksymalną długość skrajnych prawych znaków.

public static string Right(this string sValue, int iMaxLength)
{
  //Check if the value is valid
  if (string.IsNullOrEmpty(sValue))
  {
    //Set valid empty string as string could be null
    sValue = string.Empty;
  }
  else if (sValue.Length > iMaxLength)
  {
    //Make the string no longer than the max length
    sValue = sValue.Substring(sValue.Length - iMaxLength, iMaxLength);
  }

  //Return the string
  return sValue;
}

Indeks początkowy również nie może być mniejszy niż 0.
James

2
@James - Nie będzie tak, jak sValue.Length > iMaxLengthprzed wywołaniem podciągu!
stevehipwell

3
Świetna odpowiedź, ale zobaczenie węgierskiej notacji w kodzie C # wymagało trochę podwójnego podejścia.
Jerad Rose

1
@JeradRose - Pracuję w projekcie, w którym baza kodu wyewoluowała z aplikacji VB3 (w większości jest to VB.NET), więc są tam pewne pozostałości.
stevehipwell

4
@Jalle, VB.NET ma Left, Right i Mid jako funkcje najwyższego poziomu oraz wiele innych przydatnych rzeczy, które nie są częścią C #. Nie wiem dlaczego, ponieważ wiele z nich to przyzwoite funkcje.
składnik_15939

40

Prawdopodobnie przyjemniej jest użyć metody rozszerzenia:

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

Stosowanie

string myStr = "PER 343573";
string subStr = myStr.Right(6);

19
Następnie zgłosiłby wyjątek NullReferenceException, tak jak w przypadku próby użycia dowolnej metody na łańcuchu zerowym ...
James

1
str.Length - lengthmoże być negatywne. Również drugi parametr jest opcjonalny. Nie musisz przekraczać długości.
iheartcsharp

1
@ JMS10 to z pewnością mogłoby być, ale to bardziej dotyczy dzwoniących niż moich. Poza tym, tak słuszna uwaga, możesz użyć zastąpienia, które pobiera tutaj tylko pojedynczy parametr.
James

str? .Substring (str.Length - długość, długość);
Ludwo,

26
using System;

public static class DataTypeExtensions
{
    #region Methods

    public static string Left(this string str, int length)
    {
        str = (str ?? string.Empty);
        return str.Substring(0, Math.Min(length, str.Length));
    }

    public static string Right(this string str, int length)
    {
        str = (str ?? string.Empty);
        return (str.Length >= length)
            ? str.Substring(str.Length - length, length)
            : str;
    }

    #endregion
}

Nie powinien popełniać błędu, zwraca wartości null jako pusty ciąg, zwraca wartości przycięte lub podstawowe. Użyj go jak "testx" .Left (4) lub str.Right (12);


13

MSDN

String mystr = "PER 343573";
String number = mystr.Substring(mystr.Length-6);

EDYCJA: zbyt wolno ...


9

jeśli nie jesteś pewien długości swojego ciągu, ale jesteś pewien liczby słów (w tym przypadku zawsze 2 słowa, np. „xxx yyyyyy”), lepiej użyj split.

string Result = "PER 343573".Split(" ")[1];

to zawsze zwraca drugie słowo twojego ciągu.


Tak; załóżmy po prostu, że tekst OP ZAWSZE ma spacje; jak na swoim przykładzie :)
Christian

1
Hei Christian :) wszyscy znamy więcej niż kilka linijek odpowiedzi. Po prostu odpowiedziałem na to pytanie w skrócie, oczywiście, w prawdziwym kodzie jest o wiele więcej rzeczy do rozważenia.
Mahdi Tahsildari

7

Nie jest to dokładnie to, o co prosisz, ale patrząc na przykład, wydaje się, że szukasz numerycznej części ciągu.

Jeśli tak jest zawsze, dobrym sposobem na zrobienie tego byłoby użycie wyrażenia regularnego.

var regex= new Regex("\n+");
string numberString = regex.Match(page).Value;

-1 wyrażenia regularne są trochę przesadą w przypadku czegoś takiego, zwłaszcza gdy istnieją już wbudowane metody do tego.
James

1
Nie będę argumentował za użyciem tej metody, jeśli naprawdę potrzebujesz tylko ostatnich 6, ale jeśli Twoim celem jest wyodrębnienie liczby (takiej jak identyfikator), która może zmienić się na 5 lub 7 cyfr w pewnym momencie w przyszłości, to to lepszy sposób.
dreszcze42

1
Stara odpowiedź, ale +1 do obsługi wyrażeń regularnych. Zwłaszcza, że ​​nie ma (nadal) żadnych wbudowanych metod w implementacji String .NET do zrobienia tego @James. W przeciwnym razie to pytanie mogłoby nigdy nie istnieć.
CrazyIvan1974

@ CrazyIvan1974 nie jestem pewien, dlaczego wspomniałeś o mnie w swoim komentarzu
James

5

Użyj tego:

String text = "PER 343573";
String numbers = text;
if (text.Length > 6)
{
    numbers = text.Substring(text.Length - 6);
}

tekst? .Substring (text.Length - 6)
Ludwo

5

Zgaduję twoje wymagania, ale poniższe wyrażenie regularne zwróci tylko 6 znaków alfanumerycznych przed końcem ciągu i nie będzie pasować w innym przypadku.

string result = Regex.Match("PER 343573", @"[a-zA-Z\d]{6}$").Value;

Czy to rozwiązanie nie spełnia w uzasadniony sposób niejasnych wymagań? Jeśli nie, prosimy o wyjaśnienie swojego głosowania przeciw.
Wade

5

Ponieważ używasz .NET, który kompiluje się do MSIL , po prostu odwołaj się do Microsoft.VisualBasic i użyj wbudowanej Strings.Rightmetody firmy Microsoft :

using Microsoft.VisualBasic;
...
string input = "PER 343573";
string output = Strings.Right(input, 6);

Nie ma potrzeby tworzenia niestandardowej metody rozszerzenia ani innej pracy. Wynik uzyskuje się za pomocą jednego odniesienia i jednego prostego wiersza kodu.

Jako dalsze informacje na ten temat, użycie metod języka Visual Basic w języku C # zostało udokumentowane w innym miejscu . Osobiście natknąłem się na to pierwszy, próbując przeanalizować plik i stwierdziłem, że ten wątek SO dotyczący używania Microsoft.VisualBasic.FileIO.TextFieldParserklasy jest niezwykle przydatny do analizowania plików .csv.


To podejście zostało również szczegółowo opisane w innym wątku SO tutaj: stackoverflow.com/a/15255454/2658159
Aaron Thomas

To jest MENTALNE! Ale jako gość z VB, miło jest choć raz panować nad CSharpers!
SteveCinq

5
var str = "PER 343573";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty 
             : str.Length < 6 ? str 
             : str.Substring(str.Length - 6); // "343573"
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // "343573"

obsługuje to dowolną liczbę znaków w str. alternatywny kod nie obsługuje nullłańcucha. i pierwsza jest szybsza, a druga bardziej zwarta.

wolę drugi, jeśli znam strzawierający krótki ciąg. jeśli jest to długi sznurek, bardziej odpowiedni jest pierwszy.

na przykład

var str = "";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty 
             : str.Length < 6 ? str 
             : str.Substring(str.Length - 6); // ""
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // ""

lub

var str = "123";
var right6 = string.IsNullOrWhiteSpace(str) ? string.Empty 
             : str.Length < 6 ? str 
             : str.Substring(str.Length - 6); // "123"
// alternative
var alt_right6 = new string(str.Reverse().Take(6).Reverse().ToArray()); // "123"

1
Podoba mi się ta alternatywa. Szczegółowy, ale łatwy do zrozumienia i automagicznie rozwiązuje problem zbyt krótkiego ciągu.
Andrew Grothe

3

Użyj tego:

string mystr = "PER 343573"; int number = Convert.ToInt32(mystr.Replace("PER ",""));


3

Kolejne rozwiązanie, o którym nie można wspomnieć

S.Substring(S.Length < 6 ? 0 : S.Length - 6)

3

Metody zerowego bezpieczeństwa:

Ciągi krótsze niż maksymalna długość zwracająca oryginalny ciąg

Metoda rozszerzenia ciągów w prawo

public static string Right(this string input, int count) =>
    String.Join("", (input + "").ToCharArray().Reverse().Take(count).Reverse());

Metoda przedłużenia ciągu z lewej strony

public static string Left(this string input, int count) =>
    String.Join("", (input + "").ToCharArray().Take(count));

2

Oto rozwiązanie, którego używam ... Sprawdza, czy długość ciągu wejściowego nie jest mniejsza niż długość zadana. Powyższe rozwiązania, które widzę, niestety nie uwzględniają tego - co może prowadzić do awarii.

    /// <summary>
    /// Gets the last x-<paramref name="amount"/> of characters from the given string.
    /// If the given string's length is smaller than the requested <see cref="amount"/> the full string is returned.
    /// If the given <paramref name="amount"/> is negative, an empty string will be returned.
    /// </summary>
    /// <param name="string">The string from which to extract the last x-<paramref name="amount"/> of characters.</param>
    /// <param name="amount">The amount of characters to return.</param>
    /// <returns>The last x-<paramref name="amount"/> of characters from the given string.</returns>
    public static string GetLast(this string @string, int amount)
    {
        if (@string == null) {
            return @string;
        }

        if (amount < 0) {
            return String.Empty;
        }

        if (amount >= @string.Length) {
            return @string;
        } else {
            return @string.Substring(@string.Length - amount);
        }
    }

2

To jest metoda, której używam: lubię upraszczać.

private string TakeLast(string input, int num)
{
    if (num > input.Length)
    {
        num = input.Length;
    }
    return input.Substring(input.Length - num);
}

1

Tylko myśl:

public static string Right(this string @this, int length) {
    return @this.Substring(Math.Max(@this.Length - length, 0));
}

1
//s - your string
//n - maximum number of right characters to take at the end of string
(new Regex("^.*?(.{1,n})$")).Replace(s,"$1")

Ktoś oznaczył Twój post do usunięcia i widziałem go w kolejce do sprawdzenia . Myślę, że Twój post został nieprawidłowo oznaczony. Odpowiedzi zawierające tylko kod nie są niskiej jakości . Czy próbuje odpowiedzieć na pytanie? Jeśli nie, flaga. Czy jest to niepoprawne technicznie? Głosuj przeciw.
Wai Ha Lee,

1
Do kodu należy dołączyć pisemne wyjaśnienie, w jaki sposób rozwiązuje problem w PO.
Zze

1
Cóż, myślałem, że wystarczy pisemne wyjaśnienie w komentarzach, nie?
vldmrrr

0

Bez uciekania się do konwertera bitów i przesuwania bitów (trzeba mieć pewność kodowania) jest to najszybsza metoda, której używam jako metoda rozszerzenia „Right”.

string myString = "123456789123456789";

if (myString > 6)
{

        char[] cString = myString.ToCharArray();
        Array.Reverse(myString);
        Array.Resize(ref myString, 6);
        Array.Reverse(myString);
        string val = new string(myString);
}

2
Array.Reverseprzyjmuje tablicę, a nie ciąg, i if (myString.length > 6). Pomijając błędy składniowe, dlaczego byłaby to najszybsza metoda? Z pewnością samo użycie podciągów byłoby lepszym sposobem, nie wymagałoby to całego kopiowania tablic.
1800 INFORMACJE,

0

Używam Min, aby zapobiec negatywnym sytuacjom, a także obsługuję ciągi zerowe

// <summary>
    /// Returns a string containing a specified number of characters from the right side of a string.
    /// </summary>
    public static string Right(this string value, int length)
    {
        string result = value;
        if (value != null)
            result = value.Substring(0, Math.Min(value.Length, length));
        return result;
    }

0
using Microsoft.visualBasic;

 public class test{
  public void main(){
   string randomString = "Random Word";
   print (Strings.right(randomString,4));
  }
 }

wyjście to „Słowo”

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.