Recent

Author Topic: Compare String against Multiple Values  (Read 4155 times)

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
Compare String against Multiple Values
« on: October 19, 2018, 04:45:54 am »
I thought we had the capability to compare one string against multiple values, using a case statement.  I can't seem to make it work though, so I've produced the following routine.  Hoping someone can tell me an official way of doing this, but sharing the code in case there isn't.

Code: Pascal  [Select][+][-]
  1. Function IsIn(sSearch: String; Const AValues: Array Of Const): Boolean;
  2. Var
  3.   i: Integer;
  4.  
  5. Begin
  6.   Result := False;
  7.  
  8.   For i := Low(AValues) To High(AValues) Do
  9.   Begin
  10.     If (AValues[i].vType = vtAnsiString) Then
  11.       Result := Ansistring(AValues[i].vAnsiString) = sSearch;
  12.  
  13.     If Result Then
  14.       Break;
  15.   End;
  16. End;

Example of use.
Code: Pascal  [Select][+][-]
  1.     sExt := Lowercase(ExtractFileExt(sFilename));
  2.  
  3.     If IsIn(sExt, ['.pkt', '.mpg', '.mp4', '.mkv', '.avi', '.wmv', '.asf']) Then
  4.     Begin
« Last Edit: October 19, 2018, 04:47:25 am by Mike.Cornflake »
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Compare String against Multiple Values
« Reply #1 on: October 19, 2018, 05:34:55 am »
I thought we had the capability to compare one string against multiple values, using a case statement.  I can't seem to make it work though, so I've produced the following routine.  Hoping someone can tell me an official way of doing this, but sharing the code in case there isn't.

Code: Pascal  [Select][+][-]
  1. Function IsIn(sSearch: String; Const AValues: Array Of Const): Boolean;
  2. Var
  3.   i: Integer;
  4.  
  5. Begin
  6.   Result := False;
  7.  
  8.   For i := Low(AValues) To High(AValues) Do
  9.   Begin
  10.     If (AValues[i].vType = vtAnsiString) Then
  11.       Result := Ansistring(AValues[i].vAnsiString) = sSearch;
  12.  
  13.     If Result Then
  14.       Break;
  15.   End;
  16. End;

Example of use.
Code: Pascal  [Select][+][-]
  1.     sExt := Lowercase(ExtractFileExt(sFilename));
  2.  
  3.     If IsIn(sExt, ['.pkt', '.mpg', '.mp4', '.mkv', '.avi', '.wmv', '.asf']) Then
  4.     Begin

Code: Pascal  [Select][+][-]
  1. program project1;
  2. {$MODE OBJFPC}
  3. function IsKnown(const aExt:string):boolean;
  4. begin
  5.   case aExt of
  6.     '.pkt', '.mpg', '.mp4', '.mkv', '.avi', '.wmv', '.asf' : Result := True;
  7.   else
  8.     Result := False;
  9.   end;
  10. end;
  11.  
  12. begin
  13.   writeln('is .bat supported : ', isknown('.bat'));
  14.   writeln('is .mp4 supported : ', isknown('.mp4'));
  15.   readln;
  16. end.
  17.  

This works for me, at least in lazarus 1.4.4
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
Re: Compare String against Multiple Values
« Reply #2 on: October 19, 2018, 05:51:26 am »
Gah - that's the exact format of case that I was trying, my logic just didn't have the else requirement.  Must have been a stupid typo I just couldn't see.

Many thanks @Taazz :-)
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

wadman

  • New Member
  • *
  • Posts: 37
    • wadman's home
Re: Compare String against Multiple Values
« Reply #3 on: October 19, 2018, 07:18:29 am »
Simple. :)


if Pos('.asf', '.pkt.mpg.mp4.mkv.avi.wmv.asf') > 0 then ShowMessage('Supported');

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1260
Re: Compare String against Multiple Values
« Reply #4 on: October 19, 2018, 07:21:01 am »
if Pos('.asf', '.pkt.mpg.mp4.mkv.avi.wmv.asf') > 0 then ShowMessage('Supported');

That's genius, and yes - would have worked perfectly for me :-)   
Lazarus Trunk/FPC Trunk on Windows [7, 10]
  Have you tried searching this forum or the wiki?:   http://wiki.lazarus.freepascal.org/Alternative_Main_Page
  BOOKS! (Free and otherwise): http://wiki.lazarus.freepascal.org/Pascal_and_Lazarus_Books_and_Magazines

440bx

  • Hero Member
  • *****
  • Posts: 3945
Re: Compare String against Multiple Values
« Reply #5 on: October 19, 2018, 07:44:41 am »
if Pos('.asf', '.pkt.mpg.mp4.mkv.avi.wmv.asf') > 0 then ShowMessage('Supported');

That's genius, and yes - would have worked perfectly for me :-)
I wanted to mention that wadman's solution using Pos is likely more efficient (faster) than using a case statement and generates less code too, not to mention that it is easier to see at a glance which extensions are supported since they are all on one line instead of spread around many.

Using Pos in that case is simple, concise and elegant.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

creaothceann

  • Full Member
  • ***
  • Posts: 117
Re: Compare String against Multiple Values
« Reply #6 on: October 19, 2018, 09:38:48 am »
TStringList.IndexOf might be faster with a sorted list, if there are more than a few strings to compare to.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: Compare String against Multiple Values
« Reply #7 on: October 19, 2018, 01:08:17 pm »
I wanted to mention that wadman's solution using Pos is likely more efficient (faster) than using a case statement and generates less code too, not to mention that it is easier to see at a glance which extensions are supported since they are all on one line instead of spread around many.

Using Pos in that case is simple, concise and elegant.

Yeah and it gives false positives as well e.g. this will evaluate to being > 0:
Code: Pascal  [Select][+][-]
  1.   Pos('.mp', '.pkt.mpg.mp4.mkv.avi.wmv.asf')

Bart

440bx

  • Hero Member
  • *****
  • Posts: 3945
Re: Compare String against Multiple Values
« Reply #8 on: October 19, 2018, 01:18:45 pm »
I wanted to mention that wadman's solution using Pos is likely more efficient (faster) than using a case statement and generates less code too, not to mention that it is easier to see at a glance which extensions are supported since they are all on one line instead of spread around many.

Using Pos in that case is simple, concise and elegant.

Yeah and it gives false positives as well e.g. this will evaluate to being > 0:
Code: Pascal  [Select][+][-]
  1.   Pos('.mp', '.pkt.mpg.mp4.mkv.avi.wmv.asf')

Bart

Good point!.. I missed that.  Any extension that is a subset of another will create a problem..

I have a solution though... pass the application as an antivirus and false positives are acceptable ;)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

wp

  • Hero Member
  • *****
  • Posts: 11857
Re: Compare String against Multiple Values
« Reply #9 on: October 19, 2018, 01:38:35 pm »
I wanted to mention that wadman's solution using Pos is likely more efficient (faster) than using a case statement and generates less code too, not to mention that it is easier to see at a glance which extensions are supported since they are all on one line instead of spread around many.

Using Pos in that case is simple, concise and elegant.

Yeah and it gives false positives as well e.g. this will evaluate to being > 0:
Code: Pascal  [Select][+][-]
  1.   Pos('.mp', '.pkt.mpg.mp4.mkv.avi.wmv.asf')

Bart
Add a period to both strings
Code: Pascal  [Select][+][-]
  1.   Pos('.mp.', '.pkt.mpg.mp4.mkv.avi.wmv.asf.')

wadman

  • New Member
  • *
  • Posts: 37
    • wadman's home
Re: Compare String against Multiple Values
« Reply #10 on: October 19, 2018, 01:44:27 pm »
Yeah and it gives false positives as well e.g. this will evaluate to being > 0:
Let's add some code.
This will allow you to work with the extension of any length.
Code: [Select]

var ext: string;
begin
  ext := '.mp';
  if Pos(ext+'.', '.pkt.mpg.mp4.mkv.avi.wmv.asf.') > 0 then ShowMessage('Supported');
end;

wadman

  • New Member
  • *
  • Posts: 37
    • wadman's home
Re: Compare String against Multiple Values
« Reply #11 on: October 19, 2018, 01:45:18 pm »

sstvmaster

  • Sr. Member
  • ****
  • Posts: 299
Re: Compare String against Multiple Values
« Reply #12 on: October 19, 2018, 02:05:49 pm »
Or you using RegEx.

Code: Pascal  [Select][+][-]
  1. program project1;
  2. {$MODE OBJFPC}
  3. uses
  4.   RegExpr;
  5.  
  6. function IsKnown(const aExt:string):boolean;
  7. var
  8.   R: TRegExpr;
  9. begin
  10.   R:=TRegExpr.Create('\b'+aExt+'\b');
  11.   if R.Exec('.pkt.mpg.mp4.mkv.avi.wmv.asf') then result:=true else result:=false;
  12.   R.Free;
  13. end;
  14.  
  15. begin
  16.   writeln('is .bat supported : ', isknown('.bat'));
  17.   writeln('is .mp4 supported : ', isknown('.mp4'));
  18.   writeln('is .mp4 supported : ', isknown('.mp'));
  19.   readln;
  20. end.
« Last Edit: October 19, 2018, 05:29:59 pm by sstvmaster »
greetings Maik

Windows 10,
- Lazarus 2.2.6 (stable) + fpc 3.2.2 (stable)
- Lazarus 2.2.7 (fixes) + fpc 3.3.1 (main/trunk)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Compare String against Multiple Values
« Reply #13 on: October 19, 2018, 02:19:46 pm »
Leaks!! You forgot   R.Free;
« Last Edit: October 19, 2018, 02:44:25 pm by Thaddy »
Specialize a type, not a var.

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Compare String against Multiple Values
« Reply #14 on: October 20, 2018, 12:06:30 am »
A more accurate solution, which case insensitive, is:
Code: Pascal  [Select][+][-]
  1. {$APPTYPE CONSOLE}
  2. uses StrUtils;
  3.  
  4. begin
  5.   if AnsiMatchText('.MP4', ['.pkt', '.mpg', '.mp4', '.mkv', '.avi', '.wmv', '.asf']) then
  6.     Writeln('Supported');
  7.   Readln;
  8. end.

 

TinyPortal © 2005-2018