{"id":413,"date":"2019-05-28T01:41:26","date_gmt":"2019-05-28T01:41:26","guid":{"rendered":"http:\/\/www.onux.com\/jspp\/blog\/?p=413"},"modified":"2019-05-28T01:41:26","modified_gmt":"2019-05-28T01:41:26","slug":"tips-tricks-object-oriented-sorting-in-jspp-with-icomparable-t","status":"publish","type":"post","link":"https:\/\/www.onux.com\/jspp\/blog\/tips-tricks-object-oriented-sorting-in-jspp-with-icomparable-t\/","title":{"rendered":"Tips &#038; Tricks: Object-oriented Sorting in JS++ with IComparable&lt;T&gt;"},"content":{"rendered":"<p>JS++ makes object-oriented sorting easy with the <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/IComparable\" target=\"_blank\" rel=\"noopener noreferrer\">IComparable&lt;T&gt;<\/a> interface and the <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Comparison\" target=\"_blank\" rel=\"noopener noreferrer\">Comparison enumeration<\/a> for type-safe (and readable) comparisons.<\/p>\n<p>Here&#8217;s the code. (Don&#8217;t worry; I&#8217;ll dissect it.)<\/p>\n<pre class=\"brush:jspp\">\r\nimport System;\r\n\r\nclass Employee : IComparable&lt;Employee&gt;\r\n{\r\n    private string firstName;\r\n    private string lastName;\r\n\r\n    public Employee(string firstName, string lastName) {\r\n        this.firstName = firstName;\r\n        this.lastName = lastName;\r\n    }\r\n\r\n    public Comparison compare(Employee that) {\r\n        \/\/ Sort by employee surname\r\n        return this.lastName.compare(that.lastName);\r\n    }\r\n\r\n    public override string toString() {\r\n    \treturn this.firstName + \" \" + this.lastName;\r\n    }\r\n}\r\n\r\nEmployee zig  = new Employee(\"Zig\", \"Ziglar\");\r\nEmployee john = new Employee(\"John\", \"Smith\");\r\nEmployee abe  = new Employee(\"Abe\", \"Lincoln\");\r\n\r\nEmployee[] employees = [ zig, john, abe ];\r\nemployees.sort();\r\nConsole.log(employees.join(\", \"));\r\n\r\n\/\/ Output:\r\n\/\/ Abe Lincoln, John Smith, Zig Ziglar\r\n<\/pre>\n<p>This is beautiful, object-oriented code. All of the custom sorting logic is one line of code. Let&#8217;s break down how that happens step-by-step.<\/p>\n<h3>1. Implement IComparable&lt;T&gt;<\/h3>\n<p>The first step is to implement the IComparable&lt;T&gt; interface. The interface provides only one method to implement: <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/IComparable\/compare\" rel=\"noopener noreferrer\" target=\"_blank\">compare<\/a>.<\/p>\n<p><code>compare<\/code> expects the <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Comparison\" rel=\"noopener noreferrer\" target=\"_blank\">Comparison<\/a> enumeration as a result. As we can see from the documentation, <code>Comparison<\/code> can have three possible results: LESS_THAN, GREATER_THAN, and EQUAL. While Java\/C# expect -1, 0, and 1, JS++ gives you type-safe and <em>readable<\/em> comparisons.<\/p>\n<p>IComparable&lt;T&gt; and Comparison form the basis for custom sorting.<\/p>\n<h3>2. Determine how to sort<\/h3>\n<p>We want to sort <code>Employee<\/code> objects based on the employee&#8217;s last name. In order to do this, we want to compare strings and sort in alphabetical order. While we can do this manually, the JS++ Standard Library already provides these comparisons for us for primitive types.<\/p>\n<p>All primitive types in JS++ are auto-boxed. (Don&#8217;t worry, it gets optimized away.) In addition, all primitive types implement IComparable&lt;T&gt; (which provides the <code>compare<\/code> method).<\/p>\n<p>Thus, since all primitive types provide the <code>compare<\/code> method, sorting is as easy as this one line of code:<\/p>\n<pre class=\"brush:jspp\">return this.lastName.compare(that.lastName);<\/pre>\n<p>This is calling the <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/String\/compare\" rel=\"noopener noreferrer\" target=\"_blank\"><code>System.String.compare<\/code><\/a> method, which compares strings lexicographically (in alphabetical order). (Likewise, if you wanted to compare by employee ID number, you might declare an <code>unsigned int<\/code> and use <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/UInteger32\/compare\" rel=\"noopener noreferrer\" target=\"_blank\">System.UInteger32.compare<\/a>.)<\/p>\n<p>Thus, our sorting code and implementation of IComparable&lt;T&gt;.compare is just:<\/p>\n<pre class=\"brush:jspp\">\r\npublic Comparison compare(Employee that) {\r\n    \/\/ Sort by employee surname\r\n    return this.lastName.compare(that.lastName);\r\n}\r\n<\/pre>\n<h3>3. Define toString() Behavior<\/h3>\n<p>In addition, we want to be able to easily visualize our sorted arrays. Therefore, we should define how our <code>Employee<\/code> class looks when converted to a string so we can easily call <code>System.Console.log<\/code> on it.<\/p>\n<p>JS++ internal types use a &#8220;unified type system&#8221; where everything inherits from <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Object\" rel=\"noopener noreferrer\" target=\"_blank\">System.Object<\/a>. If we look at the <code>System.Object.toString<\/code> documentation, we can see that <code>System.Object.toString<\/code> is a <code>virtual<\/code> method based on its signature:<\/p>\n<pre class=\"brush:jspp\">public virtual string toString()<\/pre>\n<p>We override it with this code:<\/p>\n<pre class=\"brush:jspp\">\r\npublic override string toString() {\r\n    return this.firstName + \" \" + this.lastName;\r\n}\r\n<\/pre>\n<p>Thus, whenever we want a string representation of our <code>Employee<\/code> object, we will get the employee&#8217;s first name followed by his last name. This will help us visualize our sorted employees.<\/p>\n<h3>4. Instantiate some Employees<\/h3>\n<p>The next lines of code instantiate the <code>Employee<\/code> class and inserts them in an array:<\/p>\n<pre class=\"brush:jspp\">\r\nEmployee zig  = new Employee(\"Zig\", \"Ziglar\");\r\nEmployee john = new Employee(\"John\", \"Smith\");\r\nEmployee abe  = new Employee(\"Abe\", \"Lincoln\");\r\n\r\nEmployee[] employees = [ zig, john, abe ];\r\n<\/pre>\n<p>Currently, the array is unsorted, and &#8220;Zig Ziglar&#8221; will be the first element.<\/p>\n<h3>5. Sort the Array<\/h3>\n<p>Sorting is as simple as one line of code:<\/p>\n<pre class=\"brush:jspp\">employees.sort();<\/pre>\n<p>It&#8217;s just one line of code because we implemented IComparable&lt;T&gt;. Instead of implementing IComparable&lt;T&gt;, we could have also used <a href=\"https:\/\/docs.onux.com\/en-US\/Developers\/JavaScript-PP\/Standard-Library\/System\/Array\/sort#overload1\" rel=\"noopener noreferrer\" target=\"_blank\">the other overload of Array.sort<\/a>, which expects a callback:<\/p>\n<pre class=\"brush:jspp\">\r\nemployees.sort(Comparison(Employee a, Employee b) {\r\n    return a.lastName.compare(b.lastName);\r\n});\r\n<\/pre>\n<p>The callback allows flexibility; for example, you may choose to sort by employee first name in some cases.<\/p>\n<p>Implementing IComparable&lt;T&gt; simply provides a default sort so you can use System.Array.sort without a callback. These are the signatures for the System.Array.sort overloads:<\/p>\n<p><code>public T[] sort() where T: IComparable&lt;T&gt;<\/code><br \/>\n<code>public T[] sort(Comparison(T element1, T element2) comparator)<\/code><\/p>\n<p>Thus, if you do not provide a callback, you are using the overload that expects a class implementing IComparable&lt;T&gt;. If you try to sort objects whose respective classes do not implement the IComparable interface, you&#8217;ll receive an error:<\/p>\n<pre>\r\n[  ERROR  ] JSPPE5056: System.Array<T>.sort()' can only sort classes implementing 'IComparable<T>'. Please implement 'IComparable<T>' for `Employee' or use 'System.Array<T>.sort(Comparison(T element1, T element2) comparator) at line 23 char 0 at test.js++\r\n<\/pre>\n<h3>6. Print the Result<\/h3>\n<p>The final step is to just print the result:<\/p>\n<pre class=\"brush:jspp\">Console.log(employees.join(\", \"));<\/pre>\n<p>Et voila!<\/p>\n<p>(The <code>toString<\/code> method we implemented earlier will get called for each element that gets joined. Thus, you get a readable output.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>JS++ makes object-oriented sorting easy with the IComparable&lt;T&gt; interface and the Comparison enumeration for type-safe (and readable) comparisons. Here&#8217;s the code. (Don&#8217;t worry; I&#8217;ll dissect it.) import System; class Employee : IComparable&lt;Employee&gt; { private string firstName; private string lastName; public Employee(string firstName, string lastName) { this.firstName = firstName; this.lastName = lastName; } public Comparison compare(Employee &hellip; <a href=\"https:\/\/www.onux.com\/jspp\/blog\/tips-tricks-object-oriented-sorting-in-jspp-with-icomparable-t\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Tips &#038; Tricks: Object-oriented Sorting in JS++ with IComparable&lt;T&gt;&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,18],"tags":[],"_links":{"self":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/413"}],"collection":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/comments?post=413"}],"version-history":[{"count":21,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/413\/revisions"}],"predecessor-version":[{"id":991,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/posts\/413\/revisions\/991"}],"wp:attachment":[{"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/media?parent=413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/categories?post=413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.onux.com\/jspp\/blog\/wp-json\/wp\/v2\/tags?post=413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}