Dsys
asked on
Compare contents of TStringLists?
I have two TStringlists.
S : Integer;
PlayList : TStringList;
strList : TStringList
.
.
.
Randomize;
S := Random(strList.Count);
if S <= fileA then begin
PlayList.Add(strList[S]);
end;
How can I perform this kind of check?
if S {is within PlayList} then
dothis
else
dothat
S : Integer;
PlayList : TStringList;
strList : TStringList
.
.
.
Randomize;
S := Random(strList.Count);
if S <= fileA then begin
PlayList.Add(strList[S]);
end;
How can I perform this kind of check?
if S {is within PlayList} then
dothis
else
dothat
Nasty way would be to iterate through PlayList in a loop, checking each item. A better way is to try something like this (it is however case sensitive and only handles exact matches:
IF PlayList.IndexOf(S) <> -1
THEN
//Item found
ELSE
//Item NOT found
The Neil =:)
IF PlayList.IndexOf(S) <> -1
THEN
//Item found
ELSE
//Item NOT found
The Neil =:)
ASKER
can you show me the nasty way of testing by iterating through PlayList in a loop, checking each item...
i tried this:
//check
IF PlayList.IndexOf(strList[S ]) <> -1 THEN
load; //song has been played load new one.
else
Play;
the if test always finds items in playlist even when it should not. See this code below gets run before the check.
//load
Randomize;
S := Random(strList.Count);
if S <= fileA then begin
PlayList.Add(strList[S]); //add one item.
end;
check;
playlist gets filled one item at a time. Where as strList is completely full of items at the begining. As playlist grows I want to skip items in it.
i tried this:
//check
IF PlayList.IndexOf(strList[S
load; //song has been played load new one.
else
Play;
the if test always finds items in playlist even when it should not. See this code below gets run before the check.
//load
Randomize;
S := Random(strList.Count);
if S <= fileA then begin
PlayList.Add(strList[S]); //add one item.
end;
check;
playlist gets filled one item at a time. Where as strList is completely full of items at the begining. As playlist grows I want to skip items in it.
Ok, try this:
FUNCTION ItemInData(sValue : STRING; stlData ; TSTringList): BOOLEAN;
VAR
iCount : LONGINT;
BEGIN
Result := FALSE;
FOR iCount := 0 TO (stlData.Count - 1)
DO
IF stlData[iCount] = sValue
THEN
Result := TRUE;
END;
Then all you need to do is call the function in your IF statement:
IF ItemInData(S, PlayList)
THEN
//Item found
ELSE
//Item not found
This will check every item in the list with the item you want to search for. If it constantly returns TRUE (ie it finds it) then there must be a problem with the data in PlayList
The Neil =:)
FUNCTION ItemInData(sValue : STRING; stlData ; TSTringList): BOOLEAN;
VAR
iCount : LONGINT;
BEGIN
Result := FALSE;
FOR iCount := 0 TO (stlData.Count - 1)
DO
IF stlData[iCount] = sValue
THEN
Result := TRUE;
END;
Then all you need to do is call the function in your IF statement:
IF ItemInData(S, PlayList)
THEN
//Item found
ELSE
//Item not found
This will check every item in the list with the item you want to search for. If it constantly returns TRUE (ie it finds it) then there must be a problem with the data in PlayList
The Neil =:)
ASKER
This does not work.
FUNCTION TfrmMain.ItemInData(sValue : STRING; stlData : TStringList): BOOLEAN;
VAR
iCount : LONGINT;
BEGIN
Result := FALSE;
FOR iCount := 0 TO (stlData.Count - 1) DO
IF stlData[iCount] = sValue THEN <===Error in Line
Result := TRUE;
END;
.
.
.
IF ItemInData(inttostr(S), PlayList) THEN
PickSong;
I have to compare the item number it could be items 1 to 10000. The number I compare is not a count, it is a list index number. That is why this always fails to find items in the list.
FUNCTION TfrmMain.ItemInData(sValue
VAR
iCount : LONGINT;
BEGIN
Result := FALSE;
FOR iCount := 0 TO (stlData.Count - 1) DO
IF stlData[iCount] = sValue THEN <===Error in Line
Result := TRUE;
END;
.
.
.
IF ItemInData(inttostr(S), PlayList) THEN
PickSong;
I have to compare the item number it could be items 1 to 10000. The number I compare is not a count, it is a list index number. That is why this always fails to find items in the list.
ASKER
This works better.
Function TfrmMain.ItemInData(sValue : String; stlData : TStringList): BOOLEAN;
Var
i : LONGINT;
x : String;
Begin
Result := FALSE;
For i := 0 To (stlData.Count - 1) Do begin
x := stlData[i];
If x = strList[S] Then
Result := True;
end;
end;
except when it gets to the last members of the list. Then the loop befome infinate. Might there be a way to end the loop if that becomes the case?
Function TfrmMain.ItemInData(sValue
Var
i : LONGINT;
x : String;
Begin
Result := FALSE;
For i := 0 To (stlData.Count - 1) Do begin
x := stlData[i];
If x = strList[S] Then
Result := True;
end;
end;
except when it gets to the last members of the list. Then the loop befome infinate. Might there be a way to end the loop if that becomes the case?
This'll work better. It still loops through the data but it'll drop out as soon as it finds the item:
Function TfrmMain.ItemInData(s : LONGINT; stlData : TStringList): BOOLEAN;
VAR
i : LONGINT;
sItem : STRING;
BEGIN
Result := FALSE;
sItem := strList[S];
i := 0;
WHILE NOT(Result) AND (i < stlData.Count)
DO
IF stlData[i] = sItem
THEN
Result := True
ELSE
i := i + 1;
END;
Alternatively just go back to using IndexOf:
IF stlData.IndexOf(strList[S] ) = -1
THEN
//Not found
ELSE
//Found
Being an idiot I didn't realise that S was an index into the list
The Neil =:)
Function TfrmMain.ItemInData(s : LONGINT; stlData : TStringList): BOOLEAN;
VAR
i : LONGINT;
sItem : STRING;
BEGIN
Result := FALSE;
sItem := strList[S];
i := 0;
WHILE NOT(Result) AND (i < stlData.Count)
DO
IF stlData[i] = sItem
THEN
Result := True
ELSE
i := i + 1;
END;
Alternatively just go back to using IndexOf:
IF stlData.IndexOf(strList[S]
THEN
//Not found
ELSE
//Found
Being an idiot I didn't realise that S was an index into the list
The Neil =:)
ASKER
Cool... I will try this when I get home. The one other issue I ran into was this. When all items have been played and there for all songs are in playList, the check procedure becomes into an infinate loop.
I tried using a really stupid idea... using a global variable and incrementing it if the variable hit 2000 I figure that would be big enough to show that it is infinate, then I use an if statement to run application.terminate; This however does not really close the program gracefully. What do you think I should do?
I tried using a really stupid idea... using a global variable and incrementing it if the variable hit 2000 I figure that would be big enough to show that it is infinate, then I use an if statement to run application.terminate; This however does not really close the program gracefully. What do you think I should do?
Why not just check to see if there are all the items in the playlist as there are in the track list? BUT, rather than checking each item, cheat and do this:
IF strList.Count = PlayList.Count
THEN
//All items played
This of course assumes that a track will only be played once. If it can be played more than once then you need to check it using something like this:
FUNCTION AllItemsPlayed(stlPlayList , stlTrackList : TStringList): BOOLEAN;
VAR
stlTemp : TStringList;
iCount : LONGINT;
BEGIN
Result := TRUE;
stlTemp := TStringList.Create;
TRY
FOR iCount := 0 TO (stlPlayList.Count - 1)
DO
IF stlTemp.IndexOf(stlPlayLis t[iCount]) = -1
THEN
stlTemp.Add(stlPlayList[iC ount]);
Result := (stlTemp.Count = stlTrackList.Count);
FINALLY
stlTemp.Free;
END;
END;
This is the same check but it makes sure that each item in the playlist only gets 'counted' once by creating a temporary list containing a single entry for each item
The Neil =:)
IF strList.Count = PlayList.Count
THEN
//All items played
This of course assumes that a track will only be played once. If it can be played more than once then you need to check it using something like this:
FUNCTION AllItemsPlayed(stlPlayList
VAR
stlTemp : TStringList;
iCount : LONGINT;
BEGIN
Result := TRUE;
stlTemp := TStringList.Create;
TRY
FOR iCount := 0 TO (stlPlayList.Count - 1)
DO
IF stlTemp.IndexOf(stlPlayLis
THEN
stlTemp.Add(stlPlayList[iC
Result := (stlTemp.Count = stlTrackList.Count);
FINALLY
stlTemp.Free;
END;
END;
This is the same check but it makes sure that each item in the playlist only gets 'counted' once by creating a temporary list containing a single entry for each item
The Neil =:)
ASKER
Maybe it should write the contents of playlist out to a txt file? so that when the program is launched again it can load the txt file and continue to not repeat. when the list is full prompt to delete the file.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
My internet is down... I will try this and let you know how it all goes, thank you for all your help.
ASKER
gFile : TEXT; <--- this line give and error. does it require a certain uses?
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;
No, it's standard Pascal. Just move it to the global variable declarations and it should work fine
The Neil =:)
The Neil =:)
ASKER
ok.. works as global but the file does not get written with:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
var
icount : integer;
begin
AssignFile(gFile, 'c:\playlist.txt');
ReWrite(gFile);
FOR iCount := 0 TO (PlayList.Count - 1) DO <-- says count =0 ?
WRITELN(gFile, PlayList[iCount]);
CloseFile(gFile);
end;
procedure TfrmMain.FormClose(Sender:
var
icount : integer;
begin
AssignFile(gFile, 'c:\playlist.txt');
ReWrite(gFile);
FOR iCount := 0 TO (PlayList.Count - 1) DO <-- says count =0 ?
WRITELN(gFile, PlayList[iCount]);
CloseFile(gFile);
end;
Well the code SHOULD be working (and yes, the counter should run from 0 - Stringlists are zero based). Have you tried stepping through the code to see what is stored in the playlist? You're not doing something stupid like freeing the playlist before you reach this point are you?
The Neil =:)
The Neil =:)
ASKER
TheNeil,
No that is what I thought too. But I will work on it. I dont want to push this question too much further. You have been very helpful and I thank you!
No that is what I thought too. But I will work on it. I dont want to push this question too much further. You have been very helpful and I thank you!
Anytime you want to bounce a question then just post it
The Neil =:)
The Neil =:)
Or do you want to know if 0<=S<PlayList.Count ?
Or do you mean how can you find out if the value strList[S] is in playList then just use:
playList.IndexOf(strList[S
It will return -1 for not found or the index number of the first matching value if it is found.