2004. február 28., szombat

How to get the number of matches when searching a string


Problem/Question/Abstract:

I want to check how many of the individual characters in a search string are matching a source string. When comparing the strings, each character position should be checked individually. Examples:
Seach string: 'ABC' / Source string: 'ABX' / Result: 2 matching positions
Seach string: 'ABC' / Source string: 'AXB' / Result: 1 matching position

Answer:

Solve 1:

Assuming the compare always starts from the beginnig of the source string, i.e. Search string: 'ABC' and Source string: 'AXAB' returns 1:

function MyStrComp(strSearch, strSource: string): integer;
var
  LenSearch, LenSource, Len: integer;
  LoopCounter: integer;
begin
  LenSearch := length(strSearch);
  LenSource := length(strSource);
  if LenSearch > LenSource then
    Len := LenSource
  else
    Len := LenSearch;
  if Len = 0 then
    Result := 0
  else
  begin
    LoopCounter := 1;
    repeat
      if (strSearch[LoopCounter] <> strSource[LoopCounter] then
        break;
        Inc(LoopCounter);
    until
    (LoopCounter > Len);
    Result := LoopCounter - 1;
  end;
end;

The above function may not be the fastest, but it should be pretty fast. If you are going to call this compare function in a loop and the search string will not change within the loop, find the length of the search string before getting in the loop, then pass it to the compare function as a parameter can save a call to the length function in the compare function.

If you know that the source string is always longer than the search string, you can skip comparing the lengths and use the length of the search string to control your repeat loop.


Solve 2:

From AdvanceStringCore www.excommunicant.co.uk. You may use this routine for non commercial purposes providing appropriate credit is given.

{Concurrent matching char elements}

function ConcurrentCountMatchingCharElements(const SourceChars, MaskChars: string;
  const CSensitive: Boolean): Integer;

{Version 1.0 (September 2000 - Lachlan Fairgrieve)
(C)2000 Excommunicant www.excommunicant.co.uk
Returns the number of times [mask[i]] and [source[i]] characters match}

var
  {initialise :
  validate strings (for length)
  Count Lengths
  normalise lengths
  Prepare Pointers (For case insensitive and standard search)
  Source Scan : For Every [Source] Char check against every [mask] char}
  NewSource, NewMask: string; {Hold normalised strings}
  SourceP, MaskP: PChar;
  index: Integer; {Source and Mask index vars}
  ScanLength: Integer; {The number of chrs to scan}
begin
  {Initialise}
  Result := 0;
  if SourceChars = '' then
    exit;
  if MaskChars = '' then
    exit;
  ScanLength := Length(SourceChars);
  if Length(MaskChars) < ScanLength then
    ScanLength := Length(MaskChars);
  {prepare string pointers}
  if not CSensitive then
  begin
    NewSource := uppercase(SourceChars);
    NewMask := uppercase(MaskChars);
    SourceP := Pointer(NewSource);
    MaskP := Pointer(NewMask);
  end
  else
  begin
    SourceP := Pointer(SourceChars);
    MaskP := Pointer(MaskChars);
  end;
  {source scan}
  for index := 1 to ScanLength do
  begin
    if MaskP^ = SourceP^ then
      inc(result);
    inc(MaskP);
    inc(SourceP);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése