Як отримати останні чотири символи з рядка в C #?


309

Припустимо, у мене є рядок:

"34234234d124"

Я хочу отримати останні чотири символи цього рядка, який є "d124". Я можу використовувати SubString, але для цього потрібна пара рядків коду, включаючи іменування змінної.

Чи можливо отримати цей результат в одному виразі за допомогою C #?


3
Що ти хочеш, коли менше чотирьох символів?
агент-j

12
4 > mystring.length ? mystring : mystring.Substring(mystring.length -4);
Джодрелл

3
В Python рішення просте: "hello world"[-4:]. Я сподіваюся, що майбутня версія C # зробить це так само просто.
Полковник Паніка

@ColonelPanic, тепер ви можете з C # 8.0: "hello world"[^4..]:-)
Frode Evensen

Відповіді:


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

Якщо ви впевнені, довжина вашої струни не менше 4, то вона ще коротша:

mystring.Substring(mystring.Length - 4);

13
Крім того, він вийде з ладу, якщо mystringменше 4 символів.
Джордж Дюкетт

3
+1, тому що я думаю, що твій трохи читабельніший ніж @ dtb's
Джордж Дакетт

Взяти пару рядків коду (про які вже знав ОП) та набивати його на один рядок - це насправді не те саме, що один вираз.
Бух Бух

1
Мені це подобається. Простий та елегантний та має максимум, тому якщо ваш рядок менше 0, ви не отримаєте виключення з індексу.
Bretticus

+1 простий і до речі, охоплює всі основи. Метод розширення, запропонований Stecya, також хороший, але трохи перебити, якщо ви це робите лише один раз.
Морваел

205

Ви можете використовувати метод розширення :

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

А потім зателефонуйте:

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

11
Мені це подобається, але, мабуть, я б просто назвав його Last (). Адже Substring () - це не GetSubstring ().
Бух Бух

21
Можливо, назвіть його Tail () як Last зіткнення з розширенням Linq Last ().
Крейг Кертіс

5
+1, щоб зробити його "набагато довшим, ніж 1 рядок". Це так прикро бачити нечитабельний код через економію рядків.
Фабіо Мілхейро

2
Або назвіть це правильно () для узгодження з VisualBasic відповідно до відповіді програміста @RJ (я не хочу додавати ще одну збірку лише для однієї функції).
christutty

3
Я люблю це рішення.
Лука

46

Все, що вам потрібно зробити, це ..

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

2
Не якщо ви хочете, щоб виняток було кинуто, якщо довжина менше 4 ...
Мілош Мрдович

45

Гаразд, тому я бачу, що це стара публікація, але чому ми переписуємо код, який вже надається в рамках?

Я б запропонував вам додати посилання на рамку DLL "Microsoft.VisualBasic"

using Microsoft.VisualBasic;
//...

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

8
Хороший приклад часу використання функціональності VB
Брайан Уайт

3
Я тебе люблю. Більшість мого досвіду програмування - це VB, тому з'ясування того, що я можу використовувати всі ті функції, з якими я так знайомий, є приголомшливим
Бен Стромбек

6
Я ніколи не можу зрозуміти, чи використовую MS.VB гарну ідею - чому вона перекидається на VisualBasicпростір імен? TextFieldParserє ще один приклад. Чому ці комунальні послуги враховуються так дивно?
ruffin

6
Я відчуваю, що це має бути прийнятою відповіддю. Навіщо заново вигадувати колесо?
Зак

2
@Bomboca: Ми можемо бути впевнені, що це триватиме до тих пір, поки Microsoft продовжує підтримувати Visual Basic. Він включений у версію 4.6, і я не можу знайти нічого чіткого чи мається на увазі від MS, що вони планують припинити підтримку VB.Net як мови розробки.
Програміст RJ


26

Використання Substring насправді досить коротке і читабельне:

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

17

Ось ще одна альтернатива, яка не повинна працювати надто погано (через відкладене виконання ):

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

Хоча метод розширення за цією метою mystring.Last(4)явно є найчистішим рішенням, хоч і трохи більше роботи.


1
@BrianWhite Люди капризні після нового року?
Конрад Вільтерстен

1
Приємне рішення. мені це подобається. Але ви забули інші Reverse, щоб отримати правильний рядок. Повинно бути: нова рядок (mystring.Reverse (). Take (4) .Reverse (). ToArray ());
Юрій Моралес

Так, ви маєте рацію - мій розумовий упорядник не думав так далеко. На жаль, це робить його ще гіршим! :)
Андре Луус

1
Через ToArray немає відкладеного виконання

1
Я не думаю, що ти розумієш, @ BjörnAliGöransson, моя думка полягала в тому, що Reverse().Take(4).Reverse()не кожен перераховує весь рядок, це відбувається лише під час останнього ToArrayдзвінка. Якби не було такого поняття, як відкладене виконання, це перекладалося б Reverse().ToArray().Take(4).ToArray().Reverse().ToArray(). Це, звичайно, передбачає, що ці розширення є відкладеним типом - що я не перевіряв. Конструктори String не приймають IEnumerable, тому вам доведеться перерахувати його до масиву в цій точці.
Андре Луус

17

Ви можете просто використовувати Substringметод C #. Для екс.

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

Це поверне результат 0000.


7
На це відповіли як 28 разів, і ви знову додали його? І навіщо використовувати перевантаження з двома параметрами замість того, що тільки отримує startIndex?
Андрій

Саме відповідь мені потрібна. Дякую за поділ @Amit Kumawat.
Дарил

12

Простим рішенням буде:

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

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

Приємно, але я думаю, що ти цього =не мав на увазі =+.
dotancohen

1
mystring.Substring (mystring.Length - 4, 4) - те саме, що: mystring.Substring (mystring.Length - 4)
Moe Howard


6

Порівняно з деякими попередніми відповідями, головна відмінність полягає в тому, що цей фрагмент коду враховується при введенні рядка:

  1. Нуль
  2. Більше або відповідне бажаній довжині
  3. Коротше, ніж потрібна довжина.

Ось:

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

Визначення:

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

Використання:

GetLast("string of", 2);

Результат:

з


3

Це не вийде з жодної довжини рядка.

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

Це, ймовірно, надмірне значення для заданої задачі, але якщо потрібна додаткова перевірка, вона, можливо, може бути додана до регулярного виразу.

Редагувати: Я думаю, що цей регулярний вираз був би більш ефективним:

@".{4}\Z"

5
Однозначно зайвий рівень. Я б дотримувався простих рядкових методів для цього.
торгує

Другий варіант не повертає трибуквенний рядок, коли його викликають з аргументом з трьома літерами, тому він не еквівалентний вашій першій геніальній версії з використанням негативного lookahead! :-)
avl_sweden

3

Використовуйте родовий Last<T>. Це буде працювати з будь-яким IEnumerable, включаючи рядок.

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

І конкретний для рядка:

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

1
Ого. Перевищення. Можливо, щось на кшталт enumerable.Skip (enumerable.Count () - nLastElements)?
Buh Buh

Я не погоджуюся з @BuhBuh з приводу того, що це надмірність. Але я віддаю перевагу «Останній» перед «Правильним» як ім’я. Я трохи пишливо перевантажуючи існуючий Last of IEnumerable <T>. Я якось схиляюся до "Пропустити" теж.
Імовірно заперечуваний

Мені подобається це рішення. Не просто, але цікаво, коли навчається IEnumerable.
pKarelian

1

Я зібрав разом якийсь код, модифікований з різних джерел, який отримає потрібні результати, та ще й багато іншого. Я дозволив отримати негативні значення int, int, що перевищують довжину рядка, а для кінцевого індексу менше, ніж початковий індекс. В останньому випадку метод повертає підрядку у зворотному порядку. Зауважень багато, але дайте мені знати, якщо щось незрозуміле чи просто божевільне. Я пограв з цим, щоб побачити, для чого все, що я можу ним використати.

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

Тож якщо у вас є рядок типу "Це метод розширення", ось кілька прикладів та результатів, які слід очікувати.

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"

Сподіваємось, ця версія комусь корисна. Він працює як звичайно, якщо ви не використовуєте жодних від’ємних чисел, і надає параметри за замовчуванням для параметрів поза діапазоном.


1
string var = "12345678";

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

// result = "5678"

1

якщо припустити, що ви хотіли, щоб рядки були між рядком, який знаходиться в 10 символів від останнього символу, і вам потрібно лише 3 символи.

Скажімо StreamSelected = "rtsp://72.142.0.230:80/SMIL-CHAN-273/4CIF-273.stream"

У вищесказаному мені потрібно витягти те, "273"що я буду використовувати в запиті до бази даних

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

Це питання явно задає останні чотири символи в рядку. Ви ніби відповідаєте на інше запитання, пов’язане з вилученням речей із середини рядка. Крім того, Substringвже дозволяє вам пройти початкову точку та довжину, тому не переконайтесь, чому ви б не скористалися цим, а не Removeдля того, щоб спочатку видалити початок.
Кріс

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.