是否有像PosEx这样的Delphi D2010函数从字符串末尾开始在字符串中找到子字符串?
我正在删除对FastStrings库的所有调用,我使用的其中一个函数是FastPosBack:
function FastPosBack(const aSourceString, aFindString : AnsiString; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
我找到了LastDelimiter,但它不是一回事,因为它只找到最后一个分隔符而我无法指定起始位置。
谢谢!
更新:在DR评论之后,我创建了此功能:
function FastPosBack(const aSourceString, aFindString : String; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
var
RevSourceString, RevFindString: string;
begin
RevSourceString := AnsiReverseString(aSourceString);
RevFindString := AnsiReverseString(aFindString);
Result := Length(aSourceString) - PosEx(RevFindString, RevSourceString, StartPos) + 1;
end;
有没有更有效的方法呢?在1000000循环周期中,Pos需要47ms而FastPosBack需要234ms才能完成。
答案 0 :(得分:8)
您可以将Pos
与ReverseString
结合使用(来自StrUtils)
答案 1 :(得分:8)
试试这个/这些:
function RPos(const aSubStr, aString : String; const aStartPos: Integer): Integer; overload;
var
i: Integer;
pStr: PChar;
pSub: PChar;
begin
pSub := Pointer(aSubStr);
for i := aStartPos downto 1 do
begin
pStr := @(aString[i]);
if (pStr^ = pSub^) then
begin
if CompareMem(pSub, pStr, Length(aSubStr)) then
begin
result := i;
EXIT;
end;
end;
end;
result := 0;
end;
function RPos(const aSubStr, aString : String): Integer; overload;
begin
result := RPos(aSubStr, aString, Length(aString) - Length(aSubStr) + 1);
end;
重载提供了一种使用最有效的startpos来调用RPos的方法,用于从字符串的最末端进行搜索,而无需自己计算。为了提高效率,在明确指定时不对startpos执行检查。
在我的SmokeTest性能测试套件中,它的速度比FastPosBack快20%(偶然包含“off by one”错误以及需要一些实际上没有使用的参数)。
答案 2 :(得分:3)
Delphi附带了一个可以在StrUtils单元中向后搜索SearchBuf
的函数。但它专门用于搜索单词,因此它可能不会按照您想要的方式运行。下面我把它包装成一个匹配你想要的界面的函数。
function FastPosBack(const aSourceString, aFindString: AnsiString;
const aSourceLen, aFindLen, StartPos: Integer): Integer;
var
Source, Match: PAnsiChar;
begin
Source := PAnsiChar(ASourceString);
Match := SearchBuf(Source, ASourceLen, ASourceLen, 0,
AFindString, [soMatchCase]);
if Assigned(Match) then
Result := Match - Source + 1
else
Result := 0;
end;
答案 3 :(得分:2)
首先,考虑是否需要速度优化解决方案。如果不太可能在实际使用中调用100000次来反转字符串并使用现有的子字符串搜索就可以了。
如果速度是一个问题,那么有很多好的资源可以自己编写。在维基百科上查找“字符串搜索算法”的想法。当我在电脑前时,我会发布一个链接和一个示例算法。我现在正在用手机打字。
更新
这是我承诺的例子:
function RPOS(pattern: string; text:string): Integer;
var patternPosition,
textPosition: Integer;
begin
Result := -1;
for textPosition := Length(text) downto 0 do
begin
for patternPosition := Length(pattern) downto 0 do
if not (pattern[patternPosition] = (text[textPosition - (Length(pattern) - patternPosition)])) then
break;
if patternPosition = 0 then
Result := textPosition -Length(pattern) + 1;
end;
end;
它基本上是一个倒置的天真(强力)字符串搜索算法。它从模式和文本的结尾开始,一直运行到开头。我可以保证它的效率低于Delphi的Pos()函数,虽然我不能说它比Pos() - ReverseString()组合更快或更慢,因为我还没有测试过它。它有一个错误,我没有找到原因。如果两个字符串相同则返回-1(未找到)。
答案 4 :(得分:2)
我使用Free Pascal的strutils函数中的RPOS变体:
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/objpas/strutils.pp?view=markup
字符串,字符串版本几乎与Deltics相同,但有变体:
Function RPosEX(C:char;const S : AnsiString;offs:cardinal):Integer; overload;
Function RPosex (Const Substr : AnsiString; Const Source : AnsiString;offs:cardinal) : Integer; overload;
Function RPos(c:char;const S : AnsiString):Integer; overload;
Function RPos (Const Substr : AnsiString; Const Source : AnsiString) : Integer; overload;
他们是FPC的LGPL +链接异常许可证,但自从我写这些许可证以来,我特此在BSD许可下发布它们。
答案 5 :(得分:1)
不在标准RTL中,而是在INDY(根据在线帮助的单元idGlobalProtocols)中,这是最近Delphi安装的一部分:
function RPos(
const ASub: String,
const AIn: String,
AStart: Integer = -1
): Integer;
答案 6 :(得分:1)
在执行搜索之前,可能添加Uppercasing或降低aSubstr和aString参数可以使Deltics的用例不敏感。在调用RPos之前,他认为他让你这样做了。但也许一个可选的参数可以完成这项工作。
Deltic的目的应该是这样的:
function RPos(const aSubStr, aString : String; const aStartPos: Integer;
const aCaseInSensitive:boolean=true): Integer; overload;
var
i, _startPos: Integer;
pStr: PChar;
pSub: PChar;
_subStr, _string: string;
begin
if aCaseInSensitive then
begin
_subStr := lowercase( aSubstr );
_string := lowercase( aString );
end
else
begin
_subStr := aSubstr:
_string := aString;
end;
pSub := Pointer(_subStr);
if aStartPos = -1 then
_startPos := Length(_string) - Length(_subStr) + 1
else
_startPos := aStartPos;
for i := _startPos downto 1 do
begin
pStr := @(_string[i]);
if (pStr^ = pSub^) then
begin
if CompareMem(pSub, pStr, Length(_subStr)) then
begin
result := i;
EXIT;
end;
end;
end;
result := 0;
end;
function RPos(const aSubStr, aString : String;
const aCaseInSensitive:boolean=true): Integer; overload;
begin
result := RPos(aSubStr, aString, Length(aString) - Length(aSubStr) + 1,
aCaseInSensitive);
end;