C# 从另一个字符串修剪字符串的第一个和最后一个实例的最佳执行方式?

C# 从另一个字符串修剪字符串的第一个和最后一个实例的最佳执行方式?,c#,string,performance,C#,String,Performance,我正在尝试从另一个字符串的开始和结束处修剪可变长度字符串的第一个实例,并且正在努力找到一种理想的方法来做到这一点,而不必对该字符串进行太多次迭代 例如,假设我有 public string ParseValue(string value, string trimFromStart, string trimFromEnd) { // ?? } 我打电话 var value = ParseValue("AAABBBCCCAAABBB", "AAAB", "BB"); 然后我希望最终结果是

我正在尝试从另一个字符串的开始和结束处修剪可变长度字符串的第一个实例,并且正在努力找到一种理想的方法来做到这一点,而不必对该字符串进行太多次迭代

例如,假设我有

public string ParseValue(string value, string trimFromStart, string trimFromEnd)
{
    // ??
}
我打电话

var value = ParseValue("AAABBBCCCAAABBB", "AAAB", "BB");
然后我希望最终结果是
value=“BBCCCAAB”


在速度和内存使用方面,实现这一目标的最佳方式是什么?

不确定这是否是最好的:

public string ParseValue(string value, string trimFromStart, string trimFromEnd)
{
  var s = value.StartsWith(trimFromStart) ? value.Substring(trimFromStart.Length) : value;
  s = s.EndsWith(trimFromEnd) ? s.Substring(0,s.Length-trimFromEnd.Length) : s;      
  return s == value ? s : ParseValue(s, trimFromStart, trimFromEnd);
}
如果您想处理这种情况,例如使
ParseValue(“ABCDE”,“ABC”,“CDE”)==”
,此代码工作正常,看起来您不想修剪两次,因此我在本版本中注释掉了
递归代码

public string ParseValue(string value, string trimFromStart, string trimFromEnd){
   bool startsWith = value.StartsWith(trimFromStart);
   bool endsWith = value.EndsWith(trimFromEnd);
   int startLength = trimFromStart.Length;
   int endLength = trimFromEnd.Length;
   if (startsWith && endsWith && value.Length <= startLength + endLength) return "";
   var s = startsWith ? value.Substring(startLength) : value;
   s = endsWith ? s.Substring(0, s.Length - endLength) : s;
   return s;// == value ? s : ParseValue(s, trimFromStart, trimFromEnd);
}
公共字符串解析值(字符串值、字符串trimFromStart、字符串trimFromEnd){
bool startsWith=value.startsWith(trimFromStart);
bool endsWith=value.endsWith(trimFromEnd);
int STARTENGH=trimFromStart.Length;
int endLength=trimFromEnd.Length;

如果(开始时为&&endsWith&&value.Length不确定它是否是最好的:

public string ParseValue(string value, string trimFromStart, string trimFromEnd)
{
  var s = value.StartsWith(trimFromStart) ? value.Substring(trimFromStart.Length) : value;
  s = s.EndsWith(trimFromEnd) ? s.Substring(0,s.Length-trimFromEnd.Length) : s;      
  return s == value ? s : ParseValue(s, trimFromStart, trimFromEnd);
}
如果您想处理这种情况,例如使
ParseValue(“ABCDE”,“ABC”,“CDE”)==”
,此代码工作正常,看起来您不想修剪两次,因此我在本版本中注释掉了
递归代码

public string ParseValue(string value, string trimFromStart, string trimFromEnd){
   bool startsWith = value.StartsWith(trimFromStart);
   bool endsWith = value.EndsWith(trimFromEnd);
   int startLength = trimFromStart.Length;
   int endLength = trimFromEnd.Length;
   if (startsWith && endsWith && value.Length <= startLength + endLength) return "";
   var s = startsWith ? value.Substring(startLength) : value;
   s = endsWith ? s.Substring(0, s.Length - endLength) : s;
   return s;// == value ? s : ParseValue(s, trimFromStart, trimFromEnd);
}
公共字符串解析值(字符串值、字符串trimFromStart、字符串trimFromEnd){
bool startsWith=value.startsWith(trimFromStart);
bool endsWith=value.endsWith(trimFromEnd);
int STARTENGH=trimFromStart.Length;
int endLength=trimFromEnd.Length;

如果(startsWith&&endsWith&&value.Length您已经回答了,但是这里有一个实现(可能需要调整),它涵盖了更多的边缘情况

public string ParseValue(string value, string trimFromStart, string trimFromEnd)
{
    int valueLength = value.Length;
    int trimStartAmount = value.StartsWith(trimFromStart) 
        ? trimFromStart.Length 
        : 0;

    int trimFromEndIndex = valueLength;
    int trimEndAmount = 0;

    if (value.EndsWith(trimFromEnd))
    {
        trimFromEndIndex = valueLength - trimFromEnd.Length;
        trimEndAmount = trimFromEnd.Length;
    }

    if (trimStartAmount >= trimFromEndIndex)
        return "";

    if (trimStartAmount == 0 && trimEndAmount == 0)
        return value;

    return value.Substring(trimStartAmount, valueLength - trimStartAmount - trimEndAmount);
}
测试:

Assert.AreEqual("C", ParseValue("ABCDE", "AB", "DE"));
Assert.AreEqual("ABC", ParseValue("ABCDE", "ABCDEF", "DE"));
Assert.AreEqual("DE", ParseValue("ABCDE", "ABC", "ABCDEF"));
Assert.AreEqual("", ParseValue("ABCDE", "ABC", "CDE"));
Assert.AreEqual("", ParseValue("ABCDE", "ABC", "DE"));
Assert.AreEqual("BBCCCAAAB", ParseValue("AAABBBCCCAAABBB", "AAAB", "BB"));

测试2、3、4失败,当两个字符串重叠时抛出异常。

您已经回答了,但这里有一个实现(可能需要调整),它涵盖了更多的边缘情况

public string ParseValue(string value, string trimFromStart, string trimFromEnd)
{
    int valueLength = value.Length;
    int trimStartAmount = value.StartsWith(trimFromStart) 
        ? trimFromStart.Length 
        : 0;

    int trimFromEndIndex = valueLength;
    int trimEndAmount = 0;

    if (value.EndsWith(trimFromEnd))
    {
        trimFromEndIndex = valueLength - trimFromEnd.Length;
        trimEndAmount = trimFromEnd.Length;
    }

    if (trimStartAmount >= trimFromEndIndex)
        return "";

    if (trimStartAmount == 0 && trimEndAmount == 0)
        return value;

    return value.Substring(trimStartAmount, valueLength - trimStartAmount - trimEndAmount);
}
测试:

Assert.AreEqual("C", ParseValue("ABCDE", "AB", "DE"));
Assert.AreEqual("ABC", ParseValue("ABCDE", "ABCDEF", "DE"));
Assert.AreEqual("DE", ParseValue("ABCDE", "ABC", "ABCDEF"));
Assert.AreEqual("", ParseValue("ABCDE", "ABC", "CDE"));
Assert.AreEqual("", ParseValue("ABCDE", "ABC", "DE"));
Assert.AreEqual("BBCCCAAAB", ParseValue("AAABBBCCCAAABBB", "AAAB", "BB"));


测试2、3、4失败,当两个字符串重叠时抛出异常。

你说的是可变长度,但你知道你在修剪它时要修剪什么吗?还是一种模式/未知?你的意思是前4个字符和后2个字符,可以是任何字符?@srramsakthivel“我正在修剪的[sic]值”是一个可变大小“@bradcristie要修剪的字符串是使用String.Format()构建的,参数可以是可变长度的。@Rachel你是说,
AAAB
只是一个可变字符串吗?你说的是可变长度,但你知道你在修剪它时要修剪什么吗?还是一个模式/未知?你是说前4个字符和后2个字符,可以是任何字符?@sramaskthivel“我正在修剪[sic]的值是可变大小的”@BradChristie要修剪的字符串是使用String.Format()构建的,参数可以是可变长度的。@Rachel你是说
AAAB
只是一个可变字符串吗?
“AAAABA”。TrimStart('a'));
返回
AB
。因此字符串解决方案应该类似地工作。模式可能会在开始和结束时重复多次。@QtX我认为OP不希望这样,如果这样的话,就递归调用该方法。@QtX有编译问题吗?@ChrisSinclair谢谢,你说得对,我们只能在计算后执行
子字符串
“我不太记得我评论了什么。但是我的一个测试做得很糟糕(我误读了你的部分答案,其中涉及到被评论的代码)。总之,我喜欢你的答案,这两个答案;从理解事情的角度看,似乎更合理。
“AAAABA”。TrimStart('A'));
返回
AB
。因此字符串解决方案应该类似地工作。模式可能会在开始和结束时重复多次。@QtX我认为OP不希望这样,如果这样的话,就递归调用该方法。@QtX有编译问题吗?@ChrisSinclair谢谢,你说得对,我们只能在计算后执行
子字符串
“我不太记得我评论了什么。但是我的一个测试做得很糟糕(我误读了你的部分答案,其中涉及到被评论的代码)。总之,我喜欢你的答案,这两个答案;就理解发生的事情而言,似乎更合理。对不起,
ParseValue(“AAAABAC”,“A”,“C”)”;
返回
AAABA
。我希望
BA
(正如单词
TRIM
所暗示的那样)@QtX实际上这不是我所要求的。我特别希望只从字符串的末尾修剪第一个实例,因此预期返回值为
AAABA
。我可能在编辑问题时删除了该信息,但它应该是当前版本的一部分。感谢Chris,这是一个很好的实现ts适用于所有边缘情况:)@QtX:Hrrrm,是的,我想。但是说实话,在阅读这个问题时,我觉得她只是想删除字符串的第一个匹配项,还是想模拟删除一行中所有匹配项的
TrimStart
/
TrimEnd
行为,这似乎有点模棱两可。@Rachel-1
我可能在编辑问题时删除了这个信息s
我知道
40K次
问题是这样的,@QtX:我的答案与相同,算法也没有太大的不同,并且在需要开始和结束修剪时使用一个
Substring
调用。你能告诉我为什么我的答案不被认为是“正确”的,所以我可以修复它吗?抱歉,但是
ParseValue(“AAAABAC”,“A”,“C”);
返回
AAABA
。我希望
BA
(正如单词
TRIM
所暗示的那样)@QtX实际上这不是我所要求的。我特别希望只从字符串的末端修剪字符串的第一个实例,因此我希望返回值
AAABA
。我可能有