C#TrimStart与字符串参数


70

我在寻找String扩展方法,TrimStart()TrimEnd()接受一个string参数。

我可以自己建一个,但我总是对看看别人如何做感兴趣。

如何才能做到这一点?


3
您的问题不是很清楚。字符串参数在调整功能中应该做什么?(假设您未引用扩展方法的强制性“此字符串”语法)
asawyer 2010年

1
因此,您需要两个功能与TrimStart / TrimEnd |相同的功能。还是您想要一个将从开始/结束处去除输入字符的字符?
布拉姆2010年

是的,功能与TrimStart和TrimEnd相同,但是接受字符串而不是char。
Mike Cole 2010年

.Net中的字符串具有Trim,TrimEnd和TrimStart,您是否不想使用它们?还是您想看看如何通过学习练习来做到这一点?
jwwishart 2010年

Answers:


102

要修剪(完全匹配的)字符串的所有匹配项,可以使用如下所示的内容:

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

修剪结束

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

修剪结束

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

16
这不是一个好的解决方案,因为它还会修剪部分匹配项:“ foobartes” .TrimEnd(“ test” .ToCharArray())导致foobar。恕我直言,只有在您完全匹配时,它才应修剪。编辑:和quickfix:修剪前添加一个target.EndsWith(trimChars)检查
魂斗罗

同意,这听起来不像操作员的要求。我当时以为他们想从更大的字符串的开头开始修剪某个字符串。只需TrimStarting字符串中的所有字符,就可以删除不完全匹配的情况。
蒂姆(Tim)

2
感谢您的string.ToCharArray()提示。
哈米德·萨德吉安

5
老实说,有关的部分TrimStart/End(trimChars.ToCharArray());确实应该删除。除非在幼稚的测试中,然后在生产使用中出现乱码,否则这几乎无法按预期工作。
克里斯·马里西奇

1
如果这样会永远循环trimString == "",也不确定您一直想要什么"12123".TimeStart("12") == "3"
smg

13

TrimStart和TrimEnd接受一个char数组。这意味着您可以像这样将字符串作为char数组传递:

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

因此,我认为不需要带有字符串参数的重载。


1
哇,真尴尬。我不知道那是怎么回事。谢谢!
Mike Cole 2010年

28
请注意,此解决方案以任何顺序匹配修剪字符。例如,如果myString="Sammy"trimChars="Sam"它将返回““ y”,但预期结果是“ my”。因此,它会修剪太多,因此不会将修剪词视作如此。
马特

1
正如@Matt解释的那样,这样做有点冒险。发生这种情况是因为Trim(Start / End)将一个char数组作为一个参数而不是一个字符串。给定该示例,您还可以拥有myString="Sammy"trimChars="SaX"; 这将导致"mmy"。确保这是您期望的行为
Andrew

11

我认为问题是试图从较大的字符串开始修剪特定的字符串。

例如,如果我有字符串“ hellohellogoodbyehello”,那么如果您尝试调用TrimStart(“ hello”),则会返回“ goodbyehello”。

如果是这种情况,则可以使用如下代码:

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

如果您需要进行大量的字符串修剪,那么这并不是超级有效,但是如果仅在少数情况下,它很简单并且可以完成工作。


5
这应该是toTrim.length,没有-1权利吗?
埃文·特里波利

4

要匹配整个字符串而不分配多个子字符串,应使用以下命令:

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

谢谢,漂亮的代码。我只是套用位变为它»if (source == null){return null;}在我的应用程序。我认为在这种情况下是更好的选择。
RAM

3

来自dotnetperls.com

性能

不幸的是,TrimStart方法没有得到很大的优化。在特定情况下,您可能将能够编写出性能优越的基于字符的迭代代码。这是因为必须创建一个数组才能使用TrimStart。

但是:自定义代码不一定需要数组。但是对于快速开发的应用程序,TrimStart方法很有用。


1
以及如何实施?我认为这是问题所在。
马特

0

C#中没有内置函数-但是您可以编写自己的扩展方法,下面将向您展示-它们可以像内置方法一样使用以修剪字符,但是在这里您可以使用字符串进行修剪。

请注意,使用IndexOf / LastIndexOf可以选择是否区分大小写/区分大小写。

我还实现了“重复修剪”功能(请参阅可选参数)。

用法:

var trimmed1 = myStr.TrimStart(trimStr); 
var trimmed2 = myStr.TrimEnd(trimStr);
var trimmed3 = myStr.TrimStr(trimStr);
var trimmed4 = myStr.Trim(trimStr);

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

创建输出

Sam
moin会吉普斯吗?gips gibts moin
gibts gips?吉普斯小玩意


请注意,TrimStr由Trim,TrimStart和TrimEnd内部使用。
马特

不同之处在于,您可以使用TrimStr来通过参数决定是要从字符串的开头还是结尾进行修剪。
马特

-1

我假设您的意思是,例如,给定字符串“ HelloWorld”并调用该函数以“ Hello”开头“修剪”您将得到“ World”。我认为这实际上是一个子字符串操作,因为您要删除一部分已知长度的字符串,而不是修剪操作,它删除未知长度的字符串。

因此,我们创建了几个扩展方法,分别名为SubstringAfterSubstringBefore。将它们包含在框架中会很不错,但是事实并非如此,因此您需要自己实现。不要忘记有一个StringComparison参数,Ordinal如果您将其设为可选,则将其用作默认值。


-1

如果您确实希望出于某种原因而没有使用内置修剪功能的情况,则假定您要使用输入字符串进行修剪,例如“〜!”。基本上与[[','〜','!']中内置的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;
}

-1

用字符串参数修剪字符串的开始/结束的函数,但只能修剪一次(不循环,这种情况更常见,可以添加一个带有附加参数的循环来触发它):

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

如前所述,如果要实现“ while循环”方法,请确保检查空字符串,否则它将永远循环。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.