Подтвердить что ты не робот

С# TrimStart со строковым параметром

Я ищу методы расширения String для TrimStart() и TrimEnd(), которые принимают строковый параметр.

Я мог бы построить его сам, но мне всегда интересно видеть, как другие люди делают что-то.

Как это можно сделать?

4b9b3361

Ответ 1

Чтобы обрезать все вхождения (точно совпадающие) строки, вы можете использовать что-то вроде следующего:

TrimStart

public static string TrimStart(this string target, string trimString)
{
    if (string.IsNullOrEmpty(trimString)) return target;

    string result = target;
    while (result.StartsWith(trimString))
    {
        result = result.Substring(trimString.Length);
    }

    return result;
}

TrimEnd

public static string TrimEnd(this string target, string trimString)
{
    if (string.IsNullOrEmpty(trimString)) return target;

    string result = target;
    while (result.EndsWith(trimString))
    {
        result = result.Substring(0, result.Length - trimString.Length);
    }

    return result;
}

Чтобы обрезать любой из символов в trimChars от начала/конца цели (например, "foobar'@"@';".TrimEnd(";@'") вернет "foobar"), вы можете использовать следующее:

TrimStart

public static string TrimStart(this string target, string trimChars)
{
    return target.TrimStart(trimChars.ToCharArray());
}

TrimEnd

public static string TrimEnd(this string target, string trimChars)
{
    return target.TrimEnd(trimChars.ToCharArray());
}

Ответ 2

TrimStart и TrimEnd берут массив символов. Это означает, что вы можете передать строку как массив char следующим образом:

var trimChars = " .+-";
var trimmed = myString.TrimStart(trimChars.ToCharArray());

Поэтому я не вижу необходимости в перегрузке, которая принимает строковый параметр.

Ответ 3

Я думал, что вопрос пытается обрезать определенную строку с начала более крупной строки.

Например, если бы у меня была строка "hellohellogoodbyehello", если вы попытались позвонить TrimStart ( "привет" ), вы вернетесь "goodbyehello".

Если это так, вы можете использовать следующий код:

string TrimStart(string source, string toTrim)
{
    string s = source;
    while (s.StartsWith(toTrim))
    {
        s = s.Substring(toTrim.Length - 1);
    }
    return s;
}

Это не было бы суперэффективно, если бы вам нужно было много обрезки строк, но если это всего лишь для нескольких случаев, это просто и выполняется.

Ответ 4

из dotnetperls.com,

Производительность

К сожалению, метод TrimStart не сильно оптимизирован. В в определенных ситуациях вы, вероятно, сможете писать на основе символов итерационный код, который может превзойти его. Это связано с тем, что массив должен создаются для использования TrimStart.

Однако: Пользовательский код не обязательно должен иметь массив. Но для быстро разработанные приложения, метод TrimStart полезен.

Ответ 5

Чтобы сопоставить всю строку и не выделять несколько подстрок, вы должны использовать следующее:

    public static string TrimStart(this string source, string value, StringComparison comparisonType)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        int valueLength = value.Length;
        int startIndex = 0;
        while (source.IndexOf(value, startIndex, comparisonType) == startIndex)
        {
            startIndex += valueLength;
        }

        return source.Substring(startIndex);
    }

    public static string TrimEnd(this string source, string value, StringComparison comparisonType)
    {
        if (source == null)
        {
            throw new ArgumentNullException(nameof(source));
        }

        int sourceLength = source.Length;
        int valueLength = value.Length;
        int count = sourceLength;
        while (source.LastIndexOf(value, count, comparisonType) == count - valueLength)
        {
            count -= valueLength;
        }

        return source.Substring(0, count);
    }

Ответ 6

В С# нет встроенной функции, но вы можете написать свои собственные расширения, которые ведут себя точно так, как вы ожидаете.

Обратите внимание, что с IndexOf/LastIndexOf вы можете выбрать, чувствителен ли он к регистру/культура или нет.

Я также использовал функцию "повторяющиеся обрезки".

Существует одна функция TrimStr(..), работающая как с обрезками, так и с тремя функциями, реализующими .TrimStart(...), .TrimEnd(...) и .Trim(..) для совместимости с .NET-обрезками:

Попробуйте в DotNetFiddle

public static class Extension
{
    public static string TrimStr(this string str, string trimStr, 
                  bool trimEnd = true, bool repeatTrim = true,
                  StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
    {
        int strLen;
        do
        {
            if (!(str ?? "").EndsWith(trimStr)) return str;
            strLen = str.Length;
            {
             if (trimEnd)
                {
                  var pos = str.LastIndexOf(trimStr, comparisonType);
                  if ((!(pos >= 0)) || (!(str.Length - trimStr.Length == pos))) break;
                  str = str.Substring(0, pos);
                }
                else
                {
                  var pos = str.IndexOf(trimStr, comparisonType);
                  if (!(pos == 0)) break;
                  str = str.Substring(trimStr.Length, str.Length - trimStr.Length);
                }
            }
        } while (repeatTrim && strLen > str.Length);
        return str;
    }

     // the following is C#6 syntax, if you're not using C#6 yet
     // replace "=> ..." by { return ... }

    public static string TrimEnd(this string str, string trimStr, 
            bool repeatTrim = true,
            StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) 
            => TrimStr(str, trimStr, true, repeatTrim, comparisonType);

    public static string TrimStart(this string str, string trimStr, 
            bool repeatTrim = true,
            StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) 
            => TrimStr(str, trimStr, false, repeatTrim, comparisonType);

    public static string Trim(this string str, string trimStr, bool repeatTrim = true,
        StringComparison comparisonType = StringComparison.OrdinalIgnoreCase) 
        => str.TrimStart(trimStr, repeatTrim, comparisonType)
              .TrimEnd(trimStr, repeatTrim, comparisonType);

}

Теперь вы можете просто использовать его как

    Console.WriteLine("Sammy".TrimEnd("my"));
    Console.WriteLine("moinmoin gibts gips? gips gibts moin".TrimStart("moin", false));
    Console.WriteLine("moinmoin gibts gips? gips gibts moin".Trim("moin").Trim());

который создает выходные данные

Сэм
moin gibts gips? gips gibts moin
gibts gips? gips gibts

Ответ 7

Я предполагаю, что вы имеете в виду, что, например, учитывая строку "HelloWorld" и вызывая функцию "обрезать" начало с помощью "Hello", вы останетесь с "World". Я бы сказал, что это действительно операция подстроки, поскольку вы удаляете часть строки известной длины, а не операцию обрезки, которая удаляет неизвестную длину строки.

Таким образом, мы создали пару методов расширения с именем SubstringAfter и SubstringBefore. Было бы неплохо иметь их в рамках, но они не настолько, что вам нужно их реализовать. Не забудьте указать параметр StringComparison и использовать Ordinal как значение по умолчанию, если вы сделаете его необязательным.

Ответ 8

Если вам нужен тот, который не использовал встроенные функции отделки по каким-либо причинам, предполагая, что вы хотите использовать строку ввода для обрезки, такую ​​как "~!" по существу, такой же, как встроенный TrimStart с ['', '~', '!']

public static String TrimStart(this string inp, string chars)
{
    while(chars.Contains(inp[0]))
    {
        inp = inp.Substring(1);
    }

    return inp;
}

public static String TrimEnd(this string inp, string chars)
{
    while (chars.Contains(inp[inp.Length-1]))
    {
        inp = inp.Substring(0, inp.Length-1);
    }

    return inp;
}

Ответ 9

Функция для обрезки начала/конца строки с помощью строкового параметра, но только один раз (без циклов, этот единственный случай более популярен, цикл может быть добавлен с дополнительным параметром для его запуска):

public static class BasicStringExtensions
{
    public static string TrimStartString(this string str, string trimValue)
    {
        if (str.StartsWith(trimValue))
            return str.TrimStart(trimValue.ToCharArray());
        //otherwise don't modify
        return str;
    }
    public static string TrimEndString(this string str, string trimValue)
    {
        if (str.EndsWith(trimValue))
            return str.TrimEnd(trimValue.ToCharArray());
        //otherwise don't modify
        return str;
    }
}

Как упомянуто ранее, если вы хотите реализовать подход "в то время как цикл", не забудьте проверить наличие пустой строки, иначе он может зацикливаться вечно.