如何使用 POS 搜索不同出现的字符串
How to search for different occurences of strings using POS
我正在尝试创建一个类似于 Delphi 的 pos 函数的函数,但我可以传递不同的字符串进行搜索,而不是只有一个。所以我可以这样调用函数:
multipos('word1#word2#word3','this is a sample text with word2',false);
// will return 'word2'
函数会return找到哪个字符串。
我做的代码在下面,它可以工作,但是太慢了。我怎样才能提高这段代码的速度?
function multipos(needles,key: string; requireAll: boolean): string;
var
k: array [1 .. 50] of string;
i, j: integer;
r, aux: string;
flag: boolean;
begin
if trim(key) = '' then
Result := ''
else
try
r := '';
Result := '';
j := 1;
for i := 1 to 50 do
k[i] := '';
for i := 1 to length(needles) do
begin
if needles[i] <> '#' then
aux := aux + needles[i]
else
begin
k[j] := aux;
Inc(j);
aux := '';
end;
if j >= 50 then
break;
end;
if aux <> '' then
k[j] := aux;
for i := 1 to j do
begin
if k[i] = '' then
break
else
if pos(lowercase(k[i]), lowercase(key)) > 0 then
begin
if not requireAll then
begin
Result := k[i];
break;
end
else
begin
r := r + k[i] + ',';
flag := i = j;
if not flag then
flag := k[i + 1] = '';
if flag then
begin
Result := r;
end;
end;
end
else
if requireAll then
begin
break;
end;
end;
except
on e: exception do
begin
Result := '';
end;
end;
end;
考虑将项目作为数组传递,例如:
function Multipos(const A: array of string; const S: string): string;
begin
for var E in A do
if Pos(E, S) > 0 then
Exit(E);
Result := ''; // Nothing found
end;
// sample calls
Multipos(['word1', 'word2', 'word3'], 'sample text with word2');
Multipos('word1#word2#word3'.Split(['#']), 'sample text with word2');
要实现 RequireAll 功能,在第一次失败时停止。在这种情况下,只需检查 return 的内容即可。
此外,TStrings/TStringList 可以满足您的需求。检查它的 Delimiter 和 DelimitedText 属性。
Marcodor的数组解法不错。这是一个 TStringList 替代方案:
function multipos(SubStrs: TStringList; Str: string; RequireAll: Boolean): string;
var
i: Integer;
begin
if (not Str.IsEmpty) and (not SubStrs.Count < 1) then
begin
Result := '';
for i := 0 to SubStrs.Count - 1 do
if Pos(SubStrs[i], Str) > 0 then
Result := Result + Copy(Str, Pos(SubStrs[i], Str), SubStrs[i].Length)
else if RequireAll then
Result := '';
end;
end;
var
myList: TStringList;
begin
myList := TStringList.Create;
myList.Delimiter := '#';
myList.DelimitedText := 'word1#word2#word3';
Writeln(multipos(myList, 'this word1is a sample word3 text with word2', False));
end.
显然您需要 system.classes 作为 StringList。也许在访问参数之前更好地检查是否一切正常,但它适用于 RequireAll True 和 False。
由于您没有指定 Delphi 版本,我假设是最新的:
function multipos(const needles,key: string; requireAll: boolean): string;
var
lst: TStringList;
begin
lst := TStringList.Create;
try
var lowerkey := key.ToLower; // do this only once
for var needle in needles.Split(['#']) do begin
if lowerkey.Contains(needle.ToLower) then begin
if not requireAll then
Exit(needle);
lst.Add(needle);
end;
end;
Result := lst.CommaText;
finally
lst.Free;
end;
end;
我正在尝试创建一个类似于 Delphi 的 pos 函数的函数,但我可以传递不同的字符串进行搜索,而不是只有一个。所以我可以这样调用函数:
multipos('word1#word2#word3','this is a sample text with word2',false);
// will return 'word2'
函数会return找到哪个字符串。
我做的代码在下面,它可以工作,但是太慢了。我怎样才能提高这段代码的速度?
function multipos(needles,key: string; requireAll: boolean): string;
var
k: array [1 .. 50] of string;
i, j: integer;
r, aux: string;
flag: boolean;
begin
if trim(key) = '' then
Result := ''
else
try
r := '';
Result := '';
j := 1;
for i := 1 to 50 do
k[i] := '';
for i := 1 to length(needles) do
begin
if needles[i] <> '#' then
aux := aux + needles[i]
else
begin
k[j] := aux;
Inc(j);
aux := '';
end;
if j >= 50 then
break;
end;
if aux <> '' then
k[j] := aux;
for i := 1 to j do
begin
if k[i] = '' then
break
else
if pos(lowercase(k[i]), lowercase(key)) > 0 then
begin
if not requireAll then
begin
Result := k[i];
break;
end
else
begin
r := r + k[i] + ',';
flag := i = j;
if not flag then
flag := k[i + 1] = '';
if flag then
begin
Result := r;
end;
end;
end
else
if requireAll then
begin
break;
end;
end;
except
on e: exception do
begin
Result := '';
end;
end;
end;
考虑将项目作为数组传递,例如:
function Multipos(const A: array of string; const S: string): string;
begin
for var E in A do
if Pos(E, S) > 0 then
Exit(E);
Result := ''; // Nothing found
end;
// sample calls
Multipos(['word1', 'word2', 'word3'], 'sample text with word2');
Multipos('word1#word2#word3'.Split(['#']), 'sample text with word2');
要实现 RequireAll 功能,在第一次失败时停止。在这种情况下,只需检查 return 的内容即可。
此外,TStrings/TStringList 可以满足您的需求。检查它的 Delimiter 和 DelimitedText 属性。
Marcodor的数组解法不错。这是一个 TStringList 替代方案:
function multipos(SubStrs: TStringList; Str: string; RequireAll: Boolean): string;
var
i: Integer;
begin
if (not Str.IsEmpty) and (not SubStrs.Count < 1) then
begin
Result := '';
for i := 0 to SubStrs.Count - 1 do
if Pos(SubStrs[i], Str) > 0 then
Result := Result + Copy(Str, Pos(SubStrs[i], Str), SubStrs[i].Length)
else if RequireAll then
Result := '';
end;
end;
var
myList: TStringList;
begin
myList := TStringList.Create;
myList.Delimiter := '#';
myList.DelimitedText := 'word1#word2#word3';
Writeln(multipos(myList, 'this word1is a sample word3 text with word2', False));
end.
显然您需要 system.classes 作为 StringList。也许在访问参数之前更好地检查是否一切正常,但它适用于 RequireAll True 和 False。
由于您没有指定 Delphi 版本,我假设是最新的:
function multipos(const needles,key: string; requireAll: boolean): string;
var
lst: TStringList;
begin
lst := TStringList.Create;
try
var lowerkey := key.ToLower; // do this only once
for var needle in needles.Split(['#']) do begin
if lowerkey.Contains(needle.ToLower) then begin
if not requireAll then
Exit(needle);
lst.Add(needle);
end;
end;
Result := lst.CommaText;
finally
lst.Free;
end;
end;