簡體   English   中英

Delphi:從字符串中刪除字符

[英]Delphi: Remove chars from string

我有一個包含字母、數字和其他字符的字符串。
我想從該字符串中刪除所有數字、點和逗號

之前:' 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('.', '');

盡管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

此解決方案使用非常少的代碼行
我只是在每次出現應該刪除的字符時拆分字符串。 在那之后,我把這些碎片放在一起,沒有刪除的字符。

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;

有多種方法可以解決此問題。 這里有三個解決方案。

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

string.Replace 有一個重載,您可以在其中傳遞標志來替換所有而不是一個。 例子:

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

編輯:等效的字符串列表:

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

使用字符串會花費更多時間,請改用 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.,');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM