10

たとえば、3つのアレイがあります。

const
  A: Array[0..9] of Byte = ($00, $01, $AA, $A1, $BB, $B1, $B2, $B3, $B4, $FF);
  B: Array[0..2] of Byte = ($A1, $BB, $B1);
  C: Array[0..2] of Byte = ($00, $BB, $FF);

各バイトを1つずつチェックする代わりに、正しいもののインデックスを比較して取得する方法はありますか?例えば:

function GetArrayIndex(Source, Value: Array of Byte): Integer;
begin
..
end;

GetArrayIndex(A, B); // results 3
GetArrayIndex(A, C); // results -1

前もって感謝します。

4

2 に答える 2

12
function ByteArrayPos(const SearchArr : array of byte; const CompArr : array of byte) : integer;
//  result=Position or -1 if not found
var
  Comp,Search : AnsiString;
begin
  SetString(Comp, PAnsiChar(@CompArr[0]), Length(CompArr));
  SetString(Search, PAnsiChar(@SearchArr[0]), Length(SearchArr));
  Result := Pos(Search,Comp) - 1;
end;
于 2012-12-01T22:50:46.243 に答える
7

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;
于 2012-12-01T23:17:47.313 に答える