【问题标题】:Is there a better way to remove a trailing part of string in .NET?有没有更好的方法来删除 .NET 中字符串的尾随部分?
【发布时间】:2012-06-12 14:59:01
【问题描述】:

要删除尾随部分,我使用代码

str.substring(0,str.length -2) 

有没有更好的方法?我特别不喜欢使用 str.length。

编辑 我希望问题尽可能简短和简单,我想我只是忽略了一些 String 方法。我试图更精确。

我需要从字符串末尾删除给定数量的字符。我不想关心字符是什么,也不想引入删除更多字符的风险。

如果数字大于字符串长度,我们就会有一个异常(字符串应该更早验证)。

我没有问题,尤其是长度问题,但是两次引用一个变量(想象一个函数而不是一个变量)。我也不喜欢减法的必要性,但这只是个人喜好。

VB.NET 解决方案

问题被标记为 vb.net 所以有 vb.net 代码(应该在一个模块中):

<System.Runtime.CompilerServices.Extension> _
Public Shared Function RemoveFromEnd(stringValue As String, removedCharacters As Integer) As String
    Return stringValue.Substring(0, stringValue.Length - removedCharacters)
End Function

【问题讨论】:

  • trailing part 是什么意思?
  • 为了删除字符串的最后 x 个字符,您必须知道它的长度。如果您只是不喜欢在代码中看到这一点,那么您可以编写一个扩展方法来隐藏计算。
  • @Duane:我的意思是删除最后的 x 个字符。
  • str.Length - 如果您的原始字符串长度为
  • 您是否有特别的原因不喜欢使用str.length

标签: .net vb.net string


【解决方案1】:

如果您关心的只是您所看到的美学,那么将此功能包装在扩展方法中是微不足道的:

    public static string RemoveFromEnd(this string stringValue, int removedCharacters)
    {
       return stringValue.Substring(0, stringValue.Length - removedCharacters);
    }

所以你可以简单地使用

    str.RemoveFromEnd(2);

并完成它。

如果您因为在非托管语言中运行缓慢而担心使用 string.length 的性能,请不要担心。由于 .Net 中的字符串是不可变的,因此 String.Length 在声明字符串时设置并且永远不会更改。因此,引用 String.Length 在 constant 时间内完成(例如,Big-O(1))并且非常快。相反,如果您对性能敏感,则应该关注 Substring 调用。在 .Net 中,子字符串在 linear 时间内完成(例如,Big-O(n)),其中 n 是原始字符串的长度。因此,它是您的代码行中的性能瓶颈。相对于字符串的长度,它会变慢。

但是,如果您正在处理很长的字符串,那么吞下它可能并不好。要解决这样的问题,您可以在扩展方法中使用 StringBuilder:

    public static string RemoveFromEnd(this string stringValue, int removedCharacters)
    {
        var newString = new StringBuilder(stringValue);
        newString.Length = newString.Length - removedCharacters;
        return newString.ToString();
    }

这应该是恒定的时间,但我需要仔细检查 Reflector 以确保 StringBuilder.Length 的行为方式与我认为的方式一致。但是,即使它是线性时间,它也相对于 removedCharacters 是线性的,这必然会低于原始字符串的长度。显然,权衡是在 StringBuilder 超出范围之前您会使用更多的内存,但如果您将它包装在一个完成速度非常快的扩展方法中,这应该不是问题。

编辑:是的,StringBuilder.Length 只返回它正在跟踪的字符串的 String.Length,以便在恒定时间内返回,并且 StringBuilder 截断方法应该尽可能快。

【讨论】:

  • 有趣。我认为StringBulider.Length 是一个只能获取的属性,但我看到你是正确的,它是获取/设置。如果增加Length,它将附加很多'\0' 字符。我想知道你什么时候会想要那个......
  • @JeppeStigNielsen 当您准备将一堆东西零碎地转储到构建器中并且不希望这些东西不断地重新分配底层数据结构时。您必须使用索引变量和其他一些我认为通常过于复杂且难以阅读的东西,不值得,但如果性能成为一个重要考虑因素,您可能只需要依靠 cmets 的魔力。
  • 当我问这个问题时,我对美学很感兴趣,但我也很欣赏有关性能的信息。您对使用 StringBuilder 更好的长度有一些估计吗?
  • @IvanH 这一切都与您的编程位置有关。由于 string.substring 处于线性时间中,因此它在数学上没有变得淫秽的临界点,因此您的字符串越长,它就会继续平稳上升。使用相对适中的机器的人可能只需要考虑几千个字符的替代方案,而使用非常强大的硬件的人可能要到 20k 才会考虑它。但就我而言,每当我需要处理文件级别的某些内容时,我倾向于使用 StringBuilder,例如 XML 文件提要或其他内容。
  • 如果子字符串是线性的且 StringBuilder 为常数,则应该有某个时间点相同,并且该点可能与硬件无关(当有足够的内存时)。
【解决方案2】:

查看这个相关问题:

Trim string from the end of a string in .NET - why is this missing?

由于没有内置方法来执行此操作,因此您需要创建自己的方法(最好是扩展方法):

public static string RemoveCharsFromEnd(this string input, int charactersToRemove) 
{
    if (input.Length > charactersToRemove) 
        return input.substring(0, input.Length - charactersToRemove);
    else
        return "";
}

【讨论】:

  • +1 用于处理应该删除整个字符串的情况。
  • 这个答案很好,但接受的答案更准确。我特别感谢我没有找到的另一个问题的链接(接受的答案不同)。
【解决方案3】:

所以确实有一种方法可以在不使用str.Length 的情况下删除字符串的第一个2 字符,即

str.Substring(2)

因此你问如何从另一端做到这一点?我不认为该框架提供了这一点。你可以使用

str.Remove(str.Length - 2)

但它使用Length

这是一种使用 Linq 且性能不佳的丑陋方式:

new string(str.Reverse().Skip(2).Reverse().ToArray())

丑陋的想法在字符串太短时不抛出异常。

【讨论】:

  • 它回答了 +1 的问题。我个人不明白为什么这个问题被投赞成票,但答案却被否决。
  • 我投了赞成票,但它太丑了,不能被接受为答案。
【解决方案4】:

这取决于您所说的“尾随部分”是什么意思。您是指内容后的空格吗?比如:

string test = "This is a test string.   "; // But you want "This is a test string."

你想删除之后的空格吗?这可以通过.Trim().TrimEnd() 命令实现。如果您不是这个意思,请说明问题所在。

【讨论】:

  • 我需要删除任意字符(不仅仅是空格或指定字符)。
  • 这没有回答问题,但您确实对其进行了适当的限定。不值得投反对票。 +1 让你平衡。
  • 谢谢布拉姆。我想回答不清楚/模糊的问题是相当冒险的。我真的认为这是最有可能的问题。
【解决方案5】:
        var test = " test";
        // Trim all trailing spaces
        test = test.Trim();
        // Trim only starting trailing spaces
        test = test.TrimStart();
        // Trim only ending trailing spaces
        test = test.TrimEnd();


        var test = "abcTest";
        // Trim all trailing abc
        var toRemove = new char[3];
        toRemove[0] = 'a';
        toRemove[1] = 'b';
        toRemove[2] = 'c';
        test = test.TrimStart(toRemove);

您应该使用 Trim() 函数来删除尾随部分

【讨论】:

  • 我需要删除任意字符(不仅仅是空格或指定字符)。
  • Trim、TrimStart 和 TrimEnd 具有重载,您可以在其中传递带有任意字符的 char[] 来删除。以下是定义:“从当前字符串的开头删除 trimChars 参数中所有出现的字符后剩余的字符串。如果 trimChars 为 null 或空数组,则删除空白字符。” msdn.microsoft.com/en-us/library/system.string.trimstart.aspx
  • “任意字符”表示他要删除最后两个字符,不管它们是什么。您提出的解决方案将要求他传递一个包含所有可能字符的char[]——全部为 65,536 个。
  • @JasonDeOliveira 假设他有一个包含 12 位数字的字符串,并且他需要一个去掉最后两位数字的字符串。然后TrimEnd 不会帮助他(即使他给了它一个包含所有数字的char[])。
  • @JimMischel 是的,然后他的整个字符串将被修剪掉:-)
猜你喜欢
  • 1970-01-01
  • 2011-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多