Andreas answer hereの作り直されたバージョンを次に示します。
function BytePos(const Pattern: array of byte; const Buffer : array of byte): Integer;
var
PatternLength,BufLength: cardinal;
i,j: cardinal;
OK: boolean;
begin
Result := -1;
PatternLength := Length(Pattern);
BufLength := Length(Buffer);
if (PatternLength > BufLength) then
Exit;
if (PatternLength = 0) then
Exit;
for i := 0 to BufLength - PatternLength do
if Buffer[i] = Pattern[0] then
begin
OK := true;
for j := 1 to PatternLength - 1 do
if Buffer[i + j] <> Pattern[j] then
begin
OK := false;
Break;
end;
if OK then
Exit(i);
end;
end;
begin
WriteLn(BytePos(B,A)); // 3
WriteLn(BytePos(C,A)); // -1
ReadLn;
end.
ただし、バミの答えは好むことです。ずっといい。
コメントに記載されているように、ただの発言です。
小さなデータセットの場合BytePos
は より優れByteArrayPos
ていますが、大きなデータセット (10000 アイテム) の場合はパフォーマンスが逆転します。
これは 32 ビット モード用であり、アセンブラーに最適化されたPos()
システム関数が大規模なデータセットに対して最適に機能します。
ただし、64 ビット モードでは、アセンブラに最適化された Pos() 関数はありません。私のベンチマーク テストでは、すべてのタイプのデータセット サイズで、 はBytePos
よりも 4 ~ 6 倍高速です。ByteArrayPos
アップデート
ベンチマークテストはXE3で行いました。
テスト中purepascal
に、System.pas 関数に欠陥のあるループを発見しましたPos()
。
改善要求QC111103が追加されました。提案された関数は約 3 倍高速です。
また、上記を少し最適化し、BytePos
以下に として示しByteposEx()
ます。
function BytePosEx(const Pattern,Buffer : array of byte; offset : Integer = 0): Integer;
var
LoopMax : Integer;
OK : Boolean;
patternP : PByte;
patStart : Byte;
i,j : NativeUInt;
begin
LoopMax := High(Buffer) - High(Pattern);
if (offset <= LoopMax) and
(High(Pattern) >= 0) and
(offset >= 0) then
begin
patternP := @Pattern[0];
patStart := patternP^;
for i := NativeUInt(@Buffer[offset]) to NativeUInt(@Buffer[LoopMax]) do
begin
if (PByte(i)^ = patStart) then
begin
OK := true;
for j := 1 to High(Pattern) do
if (PByte(i+j)^ <> patternP[j]) then
begin
OK := false;
Break;
end;
if OK then
Exit(i-NativeUInt(@Buffer[0]));
end;
end;
end;
Result := -1;
end;