Sorting a TObjectList by object property

I need to sort a list of objects by the object property "Addr", which
is a word item. The Object has a lot of other properties and methods
etc, but I need to make sure that they are in sequential order by Addr
in the list after processing.
The list is implemented as a TObjectList and I am using Delphi7 for
this project.

I have googled this and found an old thread where Wayne Niddery and
Remy Lebeau gave different solutions. The thread URL is:
https://forums.embarcadero.com/message.jspa?messageID=238358

Wayne defined a general sorting function like this:
{code}
function SortByCodeName(Item1, Item2: Pointer): Integer;
  var
    li1: TListItem absolute Item1;
    li2: TListItem absolute Item2;
begin
  //Body contains compare statements for li1 aganst li2
  ...
end;

procedure TForm12.Button1Click(Sender: TObject);
begin
  list.Sort(SortByCodeName);
end;
{code}
whereas Remy defined his solution as follows:
{code}
function MySortFunc(Item1, Item2: TListItem): Integer;
begin
  //Body compares directly properties of Item1 and Item2
  ...
end;
 
begin
  ...
  MyObjectList.Sort(TListSortCompare(@MySortFunc));
  ...
end;
{code}

So the compare functions are defined in different ways and the usage
of them is also completely differently looking.
Wayne defines local variables on top of the supplied pointer arguments
(absolute directive) whereas Remy has defined the compare function as
using the specific type of object as the arguments. So he had to make
the call in a special way by typecasting the argument function.

QUESTION
Is there not a simpler way to do this or do you need to use one or the
other of the suggested methods?
I lean towards the following variation of Waynes solution:
{code}
function SortByCodeName(Item1, Item2: Pointer): Integer;
  var
    li1: TListItem;
    li2: TListItem;
begin
  li1 := TListItem(Item1);
  li2 := TListItem(Item2);
  ...
  //Body contains compare statements for li1 aganst li2
  ...
end;

procedure TForm12.Button1Click(Sender: TObject);
begin
  list.Sort(SortByCodeName);
end;
{code}
Is this going to violate some rules concerning usage of sort functions
with TObjectList?

--

Bo Berglund
Developer in Sweden
0
Bo
7/2/2014 8:11:17 PM
embarcadero.delphi.general 4258 articles. 0 followers. Follow

6 Replies
418 Views

Similar Articles

[PageSpeed] 43

Bo wrote:

> So the compare functions are defined in different ways and the usage
> of them is also completely differently looking.

They are different only in code syntax.  Their behavior at runtime is identical.

> Is there not a simpler way to do this

No.  The alternative would be to sort the list manually, and that is certainly 
not "simpler".

> do you need to use one or the other of the suggested methods?

If you want to use the list's built-in sort routine, then yes.

> I lean towards the following variation of Waynes solution:

That is just an explicit form of what Wayne's example does.  My example eliminates 
the need for casting the parameters at all.  But the end effect is the same 
either way.  The list will be passing typed items (in your case, pointers 
to instances of your custom class type) to the sort routine, so you have 
to somehow tell the compiler that the parameters of the routine are of a 
specific type so it can access each item's members.

> Is this going to violate some rules concerning usage of sort functions
> with TObjectList?

No.

--
Remy Lebeau (TeamB)
0
Remy
7/2/2014 8:44:29 PM
On Wed, 2 Jul 2014 13:44:29 -0700, Remy Lebeau (TeamB)
<no.spam@no.spam.com> wrote:

>Bo wrote:
>
>> So the compare functions are defined in different ways and the usage
>> of them is also completely differently looking.
>
>They are different only in code syntax.  Their behavior at runtime is identical.
>
>> Is this going to violate some rules concerning usage of sort functions
>> with TObjectList?
>
>No.
Well, I tried my hand at it now and did the following:
In the class managing the list of objects I added two methods, one
private and one public:
{code}
  TElectrodeList = class
  private
    FElecs: TObjectList;
    function GetElectrode(Index: integer): TElectrode;
    function GetElectrodeCount: integer;
    function GetElectrodeByAddr(Addr: word): TElectrode;
    function CompareElectrodes(Item1, Item2: TElectrode): Integer;
  public
    constructor Create;
    destructor Destroy; override;
    property ElectrodeCount: integer read GetElectrodeCount;
    property Electrodes[Index: integer]: TElectrode read GetElectrode;
    property ElectrodeByAddr[Addr: word]: TElectrode read
GetElectrodeByAddr;
    function  Add: TElectrode;
    procedure Clear;
    procedure SortEleByAddress;
  end;

  ....
function TElectrodeList.CompareElectrodes(Item1, Item2: TElectrode):
Integer;
{Compare function passed to TobjectList.Sort()}
var
  EL1: TElectrode;
  EL2: TElectrode;
begin
  EL1 := TElectrode(Item1);
  EL2 := TElectrode(Item2);

  if EL1.Address > EL2.Address then
    Result := -1
  else if EL1.Address < EL2.Address then
    Result := 1
  else
    Result := 0;
end;

procedure TElectrodeList.SortEleByAddress;
begin
  FElecs.Sort(CompareElectrodes);
end;
{code}

But when I compile this I get an error in SortEleByAddress:
[Error] PSCmdFile.pas(881): Incompatible types: 'regular procedure and
method pointer'

Does this mean that I cannot isolate the compare function into the
object that needs it and instead I must make it a regular totally
public function????
Seems strange if that is the case, it would be more OO if it could be
contained within the object itself.

--

Bo Berglund
Developer in Sweden
0
Bo
7/2/2014 9:26:39 PM
Bo wrote:

> Well, I tried my hand at it now and did the following:
<snip>
> But when I compile this I get an error in SortEleByAddress:
> [Error] PSCmdFile.pas(881): Incompatible types: 'regular procedure
> and method pointer'

The Sort() routine cannot be a non-static class method.  Look at its declaration:

{code}
TListSortCompare = function (Item1, Item2: Pointer): Integer;

procedure Sort(Compare: TListSortCompare);
{code}

TListSortCompare is not declared as "of object", so it will not accept a 
non-static class method.  You will have to adjust your code accordingly.

> Does this mean that I cannot isolate the compare function into the
> object that needs it and instead I must make it a regular totally
> public function????

No.  You just have to declare it as 'static' to remove the portions that 
are not compatible (namely, the hidden Self parameter), for example:

{code}
TElectrodeList = class
private
  FElecs: TObjectList;
  ...
  class function CompareElectrodes(Item1, Item2: TElectrode): Integer; static;
public
  ...
  procedure SortEleByAddress;
end;

class function TElectrodeList.CompareElectrodes(Item1, Item2: TElectrode): 
Integer;
begin
  if Item1.Address > Item2.Address then
    Result := -1
  else if Item1.Address < Item2.Address then
    Result := 1
  else
    Result := 0;

  // this function can be simplified to this:
  // Result := Integer(Item2.Address) - Integer(Item1.Address);
end;

procedure TElectrodeList.SortEleByAddress;
begin
  FElecs.Sort(TListSortCompare(@CompareElectrodes));
end;
{code}

--
Remy Lebeau (TeamB)
0
Remy
7/2/2014 9:45:24 PM
On Wed, 2 Jul 2014 14:45:24 -0700, Remy Lebeau (TeamB)
<no.spam@no.spam.com> wrote:

>The Sort() routine cannot be a non-static class method.  Look at its declaration:
>
>{code}
>TListSortCompare = function (Item1, Item2: Pointer): Integer;
>
>procedure Sort(Compare: TListSortCompare);
>{code}
>
>TListSortCompare is not declared as "of object", so it will not accept a 
>non-static class method.  You will have to adjust your code accordingly.
>
>
>You just have to declare it as 'static' to remove the portions that 
>are not compatible (namely, the hidden Self parameter), for example:
>
>  class function CompareElectrodes(Item1, Item2: TElectrode): Integer; static;

I tried this but it resulted in the following strange error message on
compile:
[Error] PSCmdFile.pas(57): Field definition not allowed after methods
or properties

Maybe class functions and the static keyword is not allowed in Delphi
7?

By making the function a non-class standard function directly after
the implementation keyword there are no more compile errors.

--

Bo Berglund
Developer in Sweden
0
Bo
7/3/2014 6:20:32 AM
Bo wrote:

> Maybe class functions and the static keyword is not allowed in
> Delphi 7?

According to this page, they should be:

http://www.tindex.net/Language/staticclassmethods.html

{quote}
Class methods are available in Delphi 7 and are useful for building factory 
classes. Class methods can now be made static by adding the static keyword.
{quote}

But sure enough, the example on that page does not compile in Delphi 7.

This page:

New Delphi language features since Delphi 7 
http://edn.embarcadero.com/article/34324

Lists "static class methods" as a feature "released after the Delphi 7 version". 
 So there you go.

--
Remy Lebeau (TeamB)
0
Remy
7/3/2014 5:14:20 PM
On Thu, 3 Jul 2014 10:14:20 -0700, Remy Lebeau (TeamB)
<no.spam@no.spam.com> wrote:

>Bo wrote:
>
>> Maybe class functions and the static keyword is not allowed in
>> Delphi 7?
>
>According to this page, they should be:
>
>http://www.tindex.net/Language/staticclassmethods.html
>
>{quote}
>Class methods are available in Delphi 7 and are useful for building factory 
>classes. Class methods can now be made static by adding the static keyword.
>{quote}
>
>But sure enough, the example on that page does not compile in Delphi 7.
>
>This page:
>
>New Delphi language features since Delphi 7 
>http://edn.embarcadero.com/article/34324
>
>Lists "static class methods" as a feature "released after the Delphi 7 version". 
> So there you go.

That's life....
I am not that dogmatic that I insist on isolation, so I have put the
compare function outside the classes but not referenced in interface.
Now it works.
Maybe when I have finished the other changes I will bring the project
up in Delphi 2007 and change this just as a test.

Thanks for your help in getting the sorting working!
--

Bo Berglund
Developer in Sweden
0
Bo
7/3/2014 6:28:24 PM
Reply:

Similar Artilces:

Objects and properties of properties
Okay, this should be an easy object oriented C# question, but for some reason I have been unable to find the answer yet. I am creating an object of my own called JAddress. And basically I want to be able to do the following: JAddress.ZipCode.Text JAddress.ZipCode.MyId I am unsure on how to create the second level of properties! Doing only a first level is really easy.....public string ZipCode { get { return m_ZipCode; } set { m_ZipCode = value; } }Does anyone know how to do this? Thanks in advance, csdietrich You would have its own ZipCode type (class) which...

Sorting on fields bound to object properties
 Hi, I have implemented a custom gridview control 'SortableGridView' which handles sorting and paging of the gridview when bound to custom types (objects). However, I am not able to figure out how to get the sorting working for columns that are bound to object properties. For example, if my SortableGridView is bound to a collection of Car objects, and within the _RowDataBound event, I bind a column to the Colour of the Dashboard of the Car like this:   protected void SortableGridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.R...

Property of an object within an object
How do I access the property of an object that is within another object? For example, I have an object consisting of an ArrayList of object. The objects contained in the ArrayList have the properties DisplayText and ValueText. What is the syntax to retrieve those properties? Here's the class file code: Public Class MenuOption Public DisplayText As String Public ValueText As String Public Sub New(DisplayText As String, ValueText As String) MyBase.New() Me.DisplayText = DisplayText Me.ValueText = ValueText End Sub En...

Properties missing from object inspector Delphi XE2
I am wrestling with something really annoying. I have created a Firemonkey HD application and certain properties are missing from the object inspector. For instance, when I put a TStatusBar on a form, the Font and Text properties are missing. When I open one of the sample applications, like ControlsDemo, that also has a TStatusBar, then these properties are there! I cannot find out what's the relevant difference in settings between my app and ControlsDemo. Right-clicking on the object inspector (rightclic k > view), I see that all available properties are displayed. I have tried this o...

I want to setup property value in property page but there "Object reference not set to an instance of an object."
What is it? And how i can debug my controls? Hi, we would pretty much more information. What kind of is the property in question? Is it string, URL or what? You would be able to debug controls by having controls on separate Web Control Library project and then the actual consuming app on project that uses these controls (references the Web Control Library project). Put breakpoints on the code for your controls and run F5 in Visual Studio to start debugging (like you nornmally would). That's it.Thanks,Teemu KeiskiFinland, EU If you access childobjects of your custom control in th...

Property returns "Object" object that contains custom objects
Hi, I had some difficulties on returning the property of a custom JavaScript Object. Assuming I had a JSObject ObjA that was created using JS_NewObject with my own JSClass ObjA_class. And ObjA_class has one property getObjBs that will return a JavaScript standard "Object" object. And I want this "Object" object has properties that names are same as each ObjB object's property "id" , and the value of each properties is ObjB object. e.g. There are 2 ObjB objects: student1 and student2. The ObjB has a propperty "id": student1.id...

v12.1 allows for object properties by diagram
This is a multi-part message in MIME format. ---=_forums-1-dub44d35e3d Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Just wanted to point out that the "sub-object" symbol formatting feature of the new release addresses - in part - an often requested enhancement to support displaying different properties of an object depending on what diagram it appears on. See attachment for one example of how to use this feature > where the entity attributes of no relevance to a specific diagram are grayed out and reduced in font size. ...

Protected methods and properties in Objective-C vs Delphi
I'm presently involved in writing an iPhone app and have come against yet another learning curve. Whereas Delphi has good visibility specifiers and easy ways to declare properties and methods as private and protected, Objective-C has traditionally been a tad "imprecise" about visibility :-) For those who fancy a trip into the surreal world that is Objective-C programming, I have written a small article in my own forums - http://carterconsulting.org.uk/forums/viewtopic.php?f=3&t=18 Read it and you might be glad you still have work in Delphi ;-) Joanna ...

How to Bind to property of inner object of an object?
Hi,     In my case, I have two objects like this: 1 public class Address{ 2 private string _country; 3 public string Country { get {return _country;} set {_country=value;}} 4 5 private string _zip; 6 public string Zip { get {return _zip;} set {_zip=value;}} 7 } 8 9 public class Person{ 10 private string _firstname; 11 public string FirstName{ get {return _firstname;} set {_firstname=value;}} 12 13 private string _lastname; 14 public string LastName{ get {return _lastname;} set {_lastname=value;}} 15 ...

objectdatasource and business objects with object properties
Hi Lets say i have a business object called Customer which has a property called Address which is itself and object of type Address (in this sense there is a one-to-one relationship between Customer and Address). Lets say customer has properties forename and surname and Address has properties add1 and postcode Could you use an objectdatasource to perform updates on a customer object? For example, if your objectdatasource had a method updateCustomer(Byval c as customer) and your gridview had fields forename and surname and  add1 and postcode, would the objectdatasource know to map fore...

superreview requested: [Bug 226819] Javascript Object window should allow sort properties and methods by name : [Attachment 238736] patch v3
Jason Barnabe (np) <jason_barnabe@fastmail.fm> has asked neil@parkwaycc.co.uk <neil@httl.net> for superreview: Bug 226819: Javascript Object window should allow sort properties and methods by name https://bugzilla.mozilla.org/show_bug.cgi?id=226819 Attachment 238736: patch v3 https://bugzilla.mozilla.org/attachment.cgi?id=238736&action=edit ------- Additional Comments from Jason Barnabe (np) <jason_barnabe@fastmail.fm> Addresses all comments. I've tweaked the sort order a bit to handle arrays better: constants with numeric values sorted numerically by ...

superreview requested: [Bug 226819] Javascript Object window should allow sort properties and methods by name : [Attachment 238584] patch v2
Jason Barnabe (np) <jason_barnabe@fastmail.fm> has asked neil@parkwaycc.co.uk <neil@httl.net> for superreview: Bug 226819: Javascript Object window should allow sort properties and methods by name https://bugzilla.mozilla.org/show_bug.cgi?id=226819 Attachment 238584: patch v2 https://bugzilla.mozilla.org/attachment.cgi?id=238584&action=edit ------- Additional Comments from Jason Barnabe (np) <jason_barnabe@fastmail.fm> Bug 339396 doesn't seem to be causing errors with this patch any more. ...

superreview cancelled: [Bug 226819] Javascript Object window should allow sort properties and methods by name : [Attachment 223253] patch v1
Jason Barnabe (np) <jason_barnabe@fastmail.fm> has cancelled superreview: Bug 226819: Javascript Object window should allow sort properties and methods by name https://bugzilla.mozilla.org/show_bug.cgi?id=226819 Attachment 223253: patch v1 https://bugzilla.mozilla.org/attachment.cgi?id=223253&action=edit ...

superreview requested: [Bug 226819] Javascript Object window should allow sort properties and methods by name : [Attachment 223253] patch v1
Jason Barnabe (np) <jason_barnabe@fastmail.fm> has asked neil@parkwaycc.co.uk <neil@httl.net> for superreview: Bug 226819: Javascript Object window should allow sort properties and methods by name https://bugzilla.mozilla.org/show_bug.cgi?id=226819 Attachment 223253: patch v1 https://bugzilla.mozilla.org/attachment.cgi?id=223253&action=edit ------- Additional Comments from Jason Barnabe (np) <jason_barnabe@fastmail.fm> This patch makes the properties sorted alphabetically, case-sensitive. ...

Web resources about - Sorting a TObjectList by object property - embarcadero.delphi.general

Resources last updated: 1/12/2016 10:00:56 PM