Solved

TStrings *without* Objects

Posted on 2002-03-16
14
553 Views
Last Modified: 2013-11-23
The TStrings type associates every string it contains with an object.

I am interested in getting a new data type in which every string is associated with an integer and not associated with an object. Therefore, every item in this new type should include a string and an integer (and nothing else).

This new type, like TStrings, should be derived from TPersistent (that's the most important point).

Furthermore, the new type should retain *all* the functionality normally provided by TStrings, wih the functions normally associated with objects being transfered to the integer associated element (that is, e. g. GetOBject should become GetInteger, and so on).

I would also like this new type to be able to sort based either on the strings or on *their associated integers*. The available sorting should be either ascending or descending.

I know this is hard, and that's why I award ***300 points*** for this (I would have offered more, but 300 is the upper limit).

Is anyone up to the job?
0
Comment
Question by:rosasjo
14 Comments
 

Expert Comment

by:pin_plunder
ID: 6873144
is there any thing wrong with this?

var strings: tstringlist;
begin
  strings := tstringlist.create;
  strings.AddObject('asdfasdf', TObject(110));
  strings.free;
end;

paul.
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6873660
type
     TIntStringList=class(TStringList)
     private
          procedure SetInteger(Index: Integer; Value: Integer);
          function GetInteger(Index: Integer): Integer;
     protected
          property Objects;
     public
          property Integers[Index: Integer]: Integer read GetInteger write SetInteger;
          procedure SortByInteger;
          function IndexOfInteger(Int: Integer): Integer;
     end;

{ TIntStringList }

function TIntStringList.GetInteger(Index: Integer): Integer;
begin
     Result:=Integer(Objects[Index]);
end;

function TIntStringList.IndexOfInteger(Int: Integer): Integer;
begin
     Result:=IndexOfObject(TObject(Int));
end;

procedure TIntStringList.SetInteger(Index, Value: Integer);
begin
     Objects[Index]:=TObject(Value);
end;

function CompareInteger(List: TStringList; Index1, Index2: Integer): Integer;
begin
     Result:=Integer(List.Objects[Index2])-Integer(List.Objects[Index1]);
end;

procedure TIntStringList.SortByInteger;
begin
     CustomSort(CompareInteger);
end;
0
 

Author Comment

by:rosasjo
ID: 6873815
Thanks to both Pin Plunder and AvonWyss.

I know that I can use, and I have been using, typecasting to save integers as TObjects. The problem is that it makes my code slow, because my TStringLists do have lots of data. Furthermore, it is extremely awkward to sort a modified TStrings type (and I guess that this operation has made both of you think about a TStringList, which is the type I am actually using) by the integer stored in its TObject field.

I did state that the most important point for me is the new TStrings type to be derived from TPersistent. In fact, I don't know how to use the IStringsAdapter interface, which is not documented in the source code distributed with Delphi (it is, however, used in Classes.pas, in the declaration of the TStrings type). My intention was, once this problem would be overcome, to derive a new TStringList type that would have both a string and an integer field.

I did consider the use of an altogether different type, based on a record with a string and an integer type. But that would oblige me to rewrite too much code in order to recreate all the functionality available with TStrings and TStringList.

One part of the question was answered by AvonWyss (namely that the new type should be able to sort based either on the strings or on *their associated
integers*). AvonWyss, speaking about a TStringList, does provide a SortbyInteger routine. But there is no explicit ascending and *descending* sort.

Therefore, and even though thanking you both and being sorry for that, I can't really tell that my question has been answered.
0
 
LVL 1

Expert Comment

by:OryxConLara
ID: 6873856
rosasjo --

Do you want your asc and desc sortings to be persistant, that is, every time you decide to sort ascending or descending at runtime, for it not to need to resort?

I'm also unclear as to why you insist that the new type be derived from Persistent, and not from StringList, which itself descends from TPersistent.


0
 

Author Comment

by:rosasjo
ID: 6874058
Answer to OryxConLara:

I don't want asc and desc sortings to be persistant.

I know that TStringList descends from TPersistent (as I stated above). I would, however, like to know exactly how to create a new type, very similar to TStrings, possibly using the IStringsAdapter interface (whose contents I do not know), without object fields that I do not need and with an integer field that I very strongly need. In fact, I would like to create a new type that has features of both TStrings and TStringList (namely the sorting capability of the latter, but with the added feature of being able to do descending sorts).

I have already come up with a solution that uses an integer field and doesn't get rid of the TObjects (by simply creating a TStringList descendant and adding the functionality that I need, including an integer field in the PStringItem, and, therefore, in its PStringItemList). I also had already come up with another solution that consists in typecasting integers to TObjects, as suggested above by Pin Plunder.

But both solutions are, in my view, awkward, consume resources that I do not need and slow the code. I'm looking for a better solution than the ones I came up with. As I said, however, I acknowledge this is not an easy task (for me, anyway).
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6874259
IStringsAdapter and IStrings are for COM interoperability. They are not used inside of native Delphi applications, and they will not help solve your problem.

If you write a new type which is not derived from TStrings, you will not be able to use it just line a TString or TStringList. This is beacuse many properties and methods require you to use a TStrings desendant, and these would not accept your own implementation if it is not derived from TStrings. Therefore, it doesn't really make sense to make any kind of string collection which is not derived from TStrings.

TStringList uses some tweaks to make it faster. Especially, it does manage the initiaslization and finalization of its records manually instead of having the compiler generaste generic (less efficient for this special purpose) code. It's less probable that you will come up with a own implementation which will top it by means of performance. In a TStringList, what uses up much time, are the string operations, not the handling of the object property. The proposed implementation will work just fine without a noticeable speed penality. Sorting is done with a QuickSort and is therefore also pretty good.

As for the sorting required to be both ascending and descending, have a look at the following enhanced code of the list:

type
     TIntStringList=class(TStringList)
     private
          procedure SetInteger(Index: Integer; Value: Integer);
          function GetInteger(Index: Integer): Integer;
     protected
          property Objects;
     public
          function AddInteger(const S: string; Int: Integer): Integer;
          procedure InsertInteger(Index: Integer; const S: string; Int: Integer);
          property Integers[Index: Integer]: Integer read GetInteger write SetInteger;
          procedure SortByInteger(Ascending: Boolean);
          function IndexOfInteger(Int: Integer): Integer;
     end;

{ TIntStringList }

function TIntStringList.AddInteger(const S: string; Int: Integer): Integer;
begin
     Result:=AddObject(S,TObject(Int));
end;

function TIntStringList.GetInteger(Index: Integer): Integer;
begin
     Result:=Integer(Objects[Index]);
end;

function TIntStringList.IndexOfInteger(Int: Integer): Integer;
begin
     Result:=IndexOfObject(TObject(Int));
end;

procedure TIntStringList.InsertInteger(Index: Integer; const S: string; Int: Integer);
begin
     InsertObject(Index,S,TObject(Int));
end;

procedure TIntStringList.SetInteger(Index, Value: Integer);
begin
     Objects[Index]:=TObject(Value);
end;

function CompareIntegerAscending(List: TStringList; Index1, Index2: Integer): Integer;
begin
     Result:=Integer(List.Objects[Index2])-Integer(List.Objects[Index1]);
end;

function CompareIntegerDescending(List: TStringList; Index1, Index2: Integer): Integer;
begin
     Result:=Integer(List.Objects[Index1])-Integer(List.Objects[Index2]);
end;

procedure TIntStringList.SortByInteger(Ascending: Boolean);
begin
     if Ascending then
          CustomSort(CompareIntegerAscending)
     else
          CustomSort(CompareIntegerDescending);
end;
0
 

Author Comment

by:rosasjo
ID: 6874342
Thanks a lot to AvonWyss.

He tells me that my problem is not solvable, or would create more problems than it solves. Furthermore, he gives me a hint on where to look further in order to know a bit more about IStringsAdapter and IStrings. I believe him and consider the answer correct.

His answer retains *all* the functionality normally provided by TStrings (even though that isn't really a problem if I inherit from them).

Finally, he present an asc and desc sorting routine, as I had asked.

All in all, the answer must be considered correct: he helped me to pursue my interest in IStringsAdapter and IStrings and he persuaded me that the approach I was considering is incorrect. I therefore award him the 300 points, together with my *sincere thanks*.
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 14

Accepted Solution

by:
AvonWyss earned 300 total points
ID: 6874939
Glad to help! Thank you for the feedback.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6877730
yep, good work :-)
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6878106
rosasjo, please accept my answer so that this question is moved to the PAQ. Thank you.
0
 

Author Comment

by:rosasjo
ID: 6890287
To AvonWyss:

Sorry for the long time it took in order to give you the points I said I would give. I'm new around here and I did think that I had already done that (somehow, my action didn't come through).
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6890565
rosasjo, then let me welcome you to Experts Exchange. Since you're new here, please let me introduce you to the grading method used here.

Experts are not paid to provide answers, the only thing they receive is the feedback from the asking people. When a question is closed (that is, the asker accepts an answer and gives a grade), the grade tells the expert how well he/she helped. Also, the grade is displayed when searching the PAQ database, and it should be an appropriate rating of the quality of the answer. Therefore, you should only give a grade below an A if you weren't fully satisfied with the help provided, and only after having offered the expert to refine his answer.

For instance, note that I did provide you with a second, revised version of the list together with an explanation why IStrings and IStringsAdapter would not do what you want. So, was there anything I could have done better to answer your question?

In later questions, you may get into a situation where you want to split points among several experts, or where you want to delete a question because noone was able to provide any help. For such things, go to Community Support (the link is in the left pane) and post a 0 point question with your request. They will also change the grade of a closed question if you ask them to do to.
0
 
LVL 14

Expert Comment

by:AvonWyss
ID: 6890569
Forgot to mention: the grade you give will decide how many points the expert gets. A question worth 300 points will get the expert 1200 expert points for an A grade, 900 expert points for a B grade, and 600 expert points for a C grade. The cost to you is the same no matter what grade you give.
0
 

Author Comment

by:rosasjo
ID: 6907793
Thanks for these notions, since I really am new around here, as you mentioned.

When I gave my points and grade, it seemed me that I was giving 300 points for a thing that I had already solved and wasn't satisfied with. Now that you make me think about that, I do acknowledge that it was useful you to tell me that I can't act directly on IStringsAdapter and IStrings is indeed an important point (can't I really?!!!).

It seems me that the problem was mainly that I didn't have any means to check whether that was true or not (I still am not a 100% believer). I decided to mostly believe you (as I suspect that if you were incorrect, someone might have jumped in), but, not being 100% sure, I decided on a grade less than A (I didn't really know the answer and I still have no other source but you).

I am, however, willing to correct that grade (since your answer did make me completely change plans), and I only need to know how. Could you help me do that?

In case you can't, please accept my apologies for my lack of generosity and I ***do promise*** to be more tactful next time.

João
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now