David Schwartz 426 Posted October 21, 2021 6 hours ago, Stefan Glienke said: Wrong, string and object are in the same entry - the internal storage of a TStringList has an array of TStringItem which is a record which contains a string and an object. You simply find it like this: function findSomething( const aStringArg : string ) : TObject; var i: Integer; begin i := sl.IndexOf(aStringArg); if i >= 0 then Result := sl.Objects[i] else Result := nil; end; Make this a method in your own TStringListHelper and there you go. If you want easy and fast lookup of objects by string key, then use a dictionary. Dang, I never noticed that. I've tried everything I could think of but not this. Thanks! But it would still be nice to have a way to get the index corresponding to an iterator position in a list somehow. Share this post Link to post
David Heffernan 2345 Posted October 21, 2021 8 hours ago, Stefan Glienke said: Make this a method in your own TStringListHelper and there you go. Or better, a helper to TStrings Share this post Link to post
Fr0sT.Brutal 900 Posted October 21, 2021 (edited) 9 hours ago, David Schwartz said: for var str in sl do if (str = aStringArg) then Exit( sl.Objects[ ??? ]; // oops ... no way to get the corresponding item in Objects! JS is pretty cool here for const [str, obj] of sl if (str == aStringArg) return obj; I partially agree with you. I love for-in but the fact it hides current index makes it non-applicable in pretty much cases. Edited October 21, 2021 by Fr0sT.Brutal 1 Share this post Link to post
David Heffernan 2345 Posted October 21, 2021 Python has enumerate for this which ought to be possible for Emba to implement for Delphi in a similar manner as for in. Share this post Link to post
dummzeuch 1505 Posted October 21, 2021 4 hours ago, Darian Miller said: 'Seek' seems a little oddly named method here. That name is based on the Seek function for a file of record. Usually the reader (we have many of these for various file types) is a thin wrapper around a file of record. Depending on the file type that "thinness" varies though. Share this post Link to post
David Schwartz 426 Posted October 21, 2021 40 minutes ago, dummzeuch said: That name is based on the Seek function for a file of record. Usually the reader (we have many of these for various file types) is a thin wrapper around a file of record. Depending on the file type that "thinness" varies though. Is there a ReadBuffer operation? If not, maybe create one that's a function returning True if it read enough data and False otherwise. This way you could use a While loop to step through successive records rather than a for loop that keeps doing a seek each time just to go to the next record. The pointer should already be there, so why keep resetting it each time? Also, it bothers me that your logic uses Exceptions when something isn't found, but maybe it's that serious if data is missing. Share this post Link to post
Stefan Glienke 2002 Posted October 21, 2021 program StringListHelper; {$APPTYPE CONSOLE} uses Classes, System.SysUtils; type TStringListItem = record str: string; obj: TObject; end; TStringListPairs = record private List: TStringList; type TEnumerator = record private List: TStringList; Index: Integer; function GetCurrent: TStringListItem; public function MoveNext: Boolean; property Current: TStringListItem read GetCurrent; end; TStringListAccess = class(TStrings) private FList: TStringItemList; end; public function GetEnumerator: TEnumerator; end; TStringListHelper = class helper for TStringList public function Pairs: TStringListPairs; inline; end; { TStringListPairs.TEnumerator } function TStringListPairs.TEnumerator.GetCurrent: TStringListItem; begin Result := TStringListItem(TStringListAccess(List).FList[Index]); end; function TStringListPairs.TEnumerator.MoveNext: Boolean; begin Inc(Index); Result := Index < List.Count; end; { TStringListHelper } function TStringListHelper.Pairs: TStringListPairs; begin Result.List := Self; end; { TStringListPairs } function TStringListPairs.GetEnumerator: TEnumerator; begin Result.List := List; Result.Index := -1; end; var sl: TStringList; begin sl := TStringList.Create; for var p in sl.Pairs do if p.str = 'foo' then Writeln(p.obj.ClassName); end. 1 Share this post Link to post
David Heffernan 2345 Posted October 21, 2021 @Stefan Glienke You could readily tweak this to work with TStrings rather than TStringList and avoid all that hacking at the internals. But it's nice to see you using records for enumerators! 1 Share this post Link to post
dummzeuch 1505 Posted October 21, 2021 47 minutes ago, David Schwartz said: This way you could use a While loop to step through successive records rather than a for loop that keeps doing a seek each time just to go to the next record. The pointer should already be there, so why keep resetting it each time? Not sure I understand what you mean here. Which pointer are you talking about? And why do you think it's being reset? Depending on how the reader is implemented Seek would read a record from a file (already with a buffered stream) or from an internal data structure. In this particular case it just accesses data already read into an array. 52 minutes ago, David Schwartz said: it bothers me that your logic uses Exceptions when something isn't found, but maybe it's that serious if data is missing. It is serious in this case. The data in that file (and those associated with it) would be unusable and processing it should be stopped. 1 Share this post Link to post
Stefan Glienke 2002 Posted October 21, 2021 (edited) 5 minutes ago, David Heffernan said: @Stefan Glienke You could readily tweak this to work with TStrings rather than TStringList and avoid all that hacking at the internals. But it's nice to see you using records for enumerators! I leave that as an exercise to anyone who needs it - I would not want to have it run through the virtual Get and GetObject functions for every iteration. As for "All that hacking"- it's only that one private field access. And even that could be done a little cleaner by using the helper with Self trick. I always use records for enumerators except when I don't 😉 Edited October 21, 2021 by Stefan Glienke 3 Share this post Link to post