Delphi:从字符串中删除字符

问题描述 投票:0回答:5

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

之前:'

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
5个回答
3
投票

虽然OP自己的解决方案很好,但是效率有点低。

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

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


1
投票

有多种方法可以解决这个问题。这是三个解决方案。

解决方案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

1
投票

此解决方案适用于非常小的代码行占用空间
我只是在每次出现应该删除的字符时分割字符串。之后,我将这些碎片放在一起,没有删除的字符。

用途:

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

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;

0
投票

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

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

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

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

0
投票

使用字符串会花费更多时间,请使用 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.,');
© www.soinside.com 2019 - 2024. All rights reserved.