【问题标题】:Delphi: Remove chars from stringDelphi:从字符串中删除字符
【发布时间】:2022-07-06 02:11:40
【问题描述】:

我有一个包含字母、数字和其他字符的字符串。
我想从该字符串中删除所有数字、点和逗号

之前:'Axis moving to new position - X-Pos: 5.4mm / Y-Pos: 3.5mm'
之后:'Axis moving to new position - X-Pos mm / Y-Pos mm'

不幸的是 string.replace() 只替换一个字符。所以我需要几行。

如何避免逐行编写每个替换?

  sString := sString.Replace('0', '');
  sString := sString.Replace('1', '');
  sString := sString.Replace('2', '');
  sString := sString.Replace('3', '');
  sString := sString.Replace('3', '');
  ...
  sString := sString.Replace(':', '');
  sString := sString.Replace('.', '');

【问题讨论】:

  • 您可以为此使用正则表达式

标签: string delphi replace


【解决方案1】:

虽然OP's own solution 很好,但效率有点低。

为了完整起见,这里有一个稍微优化的版本:

function RemoveCharsFromString(const AString, AChars: string): string;
begin
  SetLength(Result, AString.Length);
  var ActualLength := 0;
  for var i := 1 to AString.Length do
  begin
    if SomePredicate(AString[i]) then
    begin
      Inc(ActualLength);
      Result[ActualLength] := AString[i];
    end;
  end;
  SetLength(Result, ActualLength);
end;

算法独立于特定谓词。在这种情况下,谓词是Pos(AString[i], AChars) = 0

【讨论】:

    【解决方案2】:

    有多种方法可以解决此问题。以下是三种解决方案。

    解决方案 1

    您可以简单地遍历源字符串,检查每个字符是否是需要删除的字符之一。

    //Simple function that loops through all characters of the source strings removing them one by one
    //It is manipulating the same string all the time
    function Removechars1(sourceString: string; sCharsToBeRemoved: string):string;
    var I: Integer;
    begin
      //Assign value of the source string to the result so we can work with result strin from now on
      result := SourceString;
      //Loop throught the whole result sring starting at end searching for characters to be removed
      //We start at the end because when we will be removing characters from the string its length
      //will be decreasing.
      for I := Length(result) downto 1 do
      begin
        //Use Pos function to see if specific character in the result string can also be found
        //in the sCharsToBeRemoved and therefore needs to be removed
        if Pos(result[i], sCharsToBeRemoved) <> 0 then
        begin
          //If so we delete the specific character
          Delete(result,I,1);
        end;
      end;
    end;
    

    解决方案 2

    第二种解决方案与第一种类似,但它依赖于在结果中添加不可移动字符。它比第一种解决方案稍慢

    //Slightly faster function that also loops through the whole sourceString character by character 
    //and adds such characters to result string if they are not present in sCharsToBeRemoved string
    function RemoveChars2(sourceString: string; sCharsToBeRemoved: string):string;
    var I: Integer;
    begin
      //Prepare enpty string for our result strung to which we will be copying our end characters
      result := '';
      //Loop through the whole string
      for I := 1 to Length(sourceString) do
      begin
        //If specific haracter can't be found in sCharsToBeRemoved copy that character to the 
        //result string
        if Pos(sourceString[I], sCharsToBeRemoved) = 0 then
        begin
          result := result + sourceString[I];
        end;
      end;
    end;
    

    解决方案 3

    第三种解决方案依赖于字符串助手来替换特定字符。这个是迄今为止最快的三个,需要的时间大约是第一个解决方案处理相同作业所需时间的一半

    //Another approach of removing characters from source string that relies on Replace string helper
    function RemoveChars3(sourceString: string; sCharsToBeRemoved: string):string;
    var I: Integer;
    begin
      //Assign value of the source string to the result so we can work with result strin from now on
      result := sourceString;
      //Loop through the sCharsToBeRemoved string so we can then call Replace string helper in order 
      //to replace all occurrences of such character in sourceString;
      for I := 1 to Length(sCharsToBeRemoved) do
      begin
        result := result.Replace(sCharsToBeRemoved[I],'');
      end;
    end;
    

    这种方法的主要优点是速度非常快,并且可以轻松修改为能够删除整个子字符串而不仅仅是单个字符。

    PS:在我的测试中,您的解决方案实际上是最慢的,比我的第一个解决方案需要多 20% 的时间

    TestTring
    jfkldajflkajdflkajlkčfjaskljflakjflkdasjflkčjdfkldafjadklfjadklfjaldkakljfkldajflkčadjslfkjadklfjlkadčjflkajdflčkjadlkfjladkdjfkladjflkadjflkčjadklčfjaldkjfkladjfklajflkadjfkadgfkljdklfjawdkojfkladsjflčaksdjdfklčasjdklčfdfklčjadslkdfjlka
    
    CharsToBeRemoved 
    asjk
    
    Solution 1
    1230 ms
    Solution 2
    1263 ms
    Solution 3
    534 ms
    Your solution
    1574 ms
    

    【讨论】:

      【解决方案3】:

      此解决方案适用于非常少的代码行
      我只是在每次出现应该删除的字符时拆分字符串。之后,我将没有删除的字符放在一起。

      uses System.SysUtils;
      
      function RemoveCharsFromString(sFullString: string; sCharsToBeRemoved: string): string;
      var
        splitted: TArray<String>;
      begin
        splitted := sFullString.Split(sCharsToBeRemoved.ToCharArray());
        Result := string.Join('', splitted);
      end;
      

      【讨论】:

      • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助,质量更高,更有可能吸引投票。
      • 我添加了一个解释。感谢您的提示:-)
      【解决方案4】:

      string.Replace 有一个重载,您可以在其中传递标志来替换所有而不是一个。示例:

      sString := sString.Replace('1', '', [rfReplaceAll, rfIgnoreCase]);
      

      编辑:等效的字符串列表:

      sString.Text := sString.Text.Replace('1', '', [rfReplaceAll, rfIgnoreCase]);
      

      【讨论】:

      • 您的解决方案只能多次替换 1 个字符,而不是字符列表。所以它没有回答问题!
      • 你说你有一个字符串。不是清单。你有什么类型的列表?
      • 我有一个字符串,但我想删除一个字符列表。我想从这个字符串中删除所有数字和点。您的解决方案只能从字符串中删除一个特定数字('1'),但不能同时删除所有字符。
      【解决方案5】:

      使用字符串会花费更多时间,请改用 PChar。 我认为这是一个稍微优化的版本

      function RemoveCharsFromString(const AString, AChars: String): String;
      var
        i, j, k, LenString, LenChars : Integer;
        PString, PChars : PChar;
      label
        Ends;
      begin
        PString := Pointer(AString);
        PChars := Pointer(AChars);
        LenString := AString.Length;
        LenChars := AChars.Length;
        k := 0;
        for i := 0 to LenString - 1 do
        begin
          for j := 0 to LenChars - 1 do
            if PString[i] = PChars[j] then
              Goto Ends;
          PString[k] := PString[i];
          Inc(k);
          Ends :
        end;
        PString[k] := #0;
        Result := StrPas(PString);
      end;
      

      如果您不喜欢标签,请使用以下代码:

      function RemoveCharsFromString(const AString, AChars: String): String;
      var
        i, j, k, LenString, LenChars : Integer;
        PString, PChars : PChar;
        found : Boolean;
      begin
        PString := Pointer(AString);
        PChars := Pointer(AChars);
        LenString := AString.Length;
        LenChars := AChars.Length;
        k := 0;
        for i := 0 to LenString - 1 do
        begin
          found := False;
          for j := 0 to LenChars - 1 do
            if PString[i] = PChars[j] then
            begin
              found := True;
              Break;
            end;
          if not found then
          begin
            PString[k] := PString[i];
            Inc(k);
          end;
        end;
        PString[k] := #0;
        Result := StrPas(PString);
      end;
      

      你可以这样称呼它:

      sString := RemoveCharsFromString(sString, '0123456789.,');
      

      【讨论】:

        猜你喜欢
        • 2011-09-19
        • 1970-01-01
        • 2016-07-26
        • 2013-09-18
        • 2011-11-22
        相关资源
        最近更新 更多