{"id":377,"date":"2020-12-20T17:06:11","date_gmt":"2020-12-20T16:06:11","guid":{"rendered":"https:\/\/mic.st\/blog\/?p=377"},"modified":"2021-01-25T07:56:07","modified_gmt":"2021-01-25T06:56:07","slug":"how-to-sort-an-array-of-objects-by-date-property","status":"publish","type":"post","link":"https:\/\/mic.st\/blog\/how-to-sort-an-array-of-objects-by-date-property\/","title":{"rendered":"How to sort an array of objects by date property"},"content":{"rendered":"\r\n<p>You might know the very handy <code>sort(by:)<\/code> method in Swift that you can use to sort any kind of array. If not, see this as some kind of friendly introduction to you. Read carefully and I will teach you now how to sort an array of custom type objects by their date property \ud83d\ude42<\/p>\r\n\r\n\r\n\r\n<p>The <code>sort(by:)<\/code> method is pretty well documented in Apple&#8217;s official documentation: <a href=\"https:\/\/developer.apple.com\/documentation\/swift\/array\/2296801-sort\" target=\"_blank\" rel=\"noopener\">https:\/\/developer.apple.com\/documentation\/swift\/array\/2296801-sort<\/a><\/p>\r\n\r\n\r\n\r\n<figure class=\"wp-block-image size-large is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"678\" class=\"wp-image-378\" src=\"https:\/\/mic.st\/blog\/wp-content\/uploads\/2020\/12\/tee-1252397_1920-1024x678.jpg\" alt=\"An image of tea bags sorted by color.\" \/>\r\n<figcaption>This has actually nothing to do with sorting something by date but these teabags are nicely sorted anyway \ud83d\ude05<\/figcaption>\r\n<\/figure>\r\n\r\n\r\n\r\n<p>In a lot of cases you just call <code>someArray.sort()<\/code>. This will sort an array of elements conforming to <code>Comparable<\/code> (e.g. <code>Int<\/code>, <code>String<\/code> and a lot of other type) in ascending order. If you want to sort it in ascending order you can just call <code>someArray.sort(by: &gt;)<\/code>. However, what if you have an array of some custom type that does not conform to <code>Comparable<\/code> and you want to sort this array by a <code>date<\/code> property this class has?<\/p>\r\n\r\n\r\n\r\n<p>A <code>ComparisonResult<\/code> can be <code>.orderedDescending<\/code>, <code>.orderedAscending<\/code> or <code>.orderedSame<\/code>. In order to sort our array of objects, we can just check these values.<\/p>\r\n\r\n\r\n\r\n<p>So how do we sort our array of objects by their <code>date<\/code> property? You can either pass in your sorting logic directly to the <code>sort(by:)<\/code> method or make your custom type conform to <code>Comparable<\/code> (which is probably the cleaner way).<\/p>\r\n\r\n\r\n\r\n<p>The documentation for <code>sort(by:)<\/code> says that you can basically do anything in the passed in closure to compare your array. So we can just do that to compare our two date properties. Thankfully, when using <code>Date<\/code>, you get a comparison method for free. It is called <code>Date.compare(_:)<\/code> and it&#8217;s great. You pass in two dates and get back a <code>ComparisonResult<\/code>. This makes your code very readable without doing anything because <code>ComparisonResult<\/code> can be either <code>.orderedAscending<\/code>, <code>.orderedDescending<\/code> or <code>.orderedSame<\/code>.<\/p>\r\n\r\n\r\n\r\n<p>In the following you can see some examples for passing in your logic directly.<\/p>\r\n\r\n\r\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Swift\" data-shcb-language-slug=\"swift\"><span><code class=\"hljs language-swift\">myElements.<span class=\"hljs-built_in\">sort<\/span>(by: { element1, element2 <span class=\"hljs-keyword\">in<\/span>\r\n    <span class=\"hljs-keyword\">let<\/span> comparisonResult = element1.date.compare(element2.date)\r\n    <span class=\"hljs-keyword\">return<\/span> comparisonResult == .orderedDescending\r\n})<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Swift<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">swift<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\r\n\r\n\r\n<p>or if you prefer the shorter syntax using <code>$<\/code>:<\/p>\r\n\r\n\r\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Swift\" data-shcb-language-slug=\"swift\"><span><code class=\"hljs language-swift\">contentForMonth.<span class=\"hljs-built_in\">sort<\/span>(by: {\r\n    <span class=\"hljs-keyword\">let<\/span> comparisonResult = $<span class=\"hljs-number\">0<\/span>.date.compare($<span class=\"hljs-number\">1<\/span>.date)\r\n    <span class=\"hljs-keyword\">return<\/span> comparisonResult == .orderedDescending\r\n})<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Swift<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">swift<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\r\n\r\n\r\n<p>or even shorter:<\/p>\r\n\r\n\r\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Swift\" data-shcb-language-slug=\"swift\"><span><code class=\"hljs language-swift\">someArray.<span class=\"hljs-built_in\">sort<\/span>(by: { $<span class=\"hljs-number\">0<\/span>.date.compare($<span class=\"hljs-number\">1<\/span>.date) == .orderedDescending })<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Swift<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">swift<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\r\n\r\n\r\n<h2 class=\"wp-block-heading\">Conforming to Comparable to easily sort an array of objects by date<\/h2>\r\n\r\n\r\n\r\n<p>Making a custom type conform to <code>Comparable<\/code> is actually easier than you might think. You just have to define two protocol methods for that. Via the first method you define in which case one object can be seen as less than a second object. The second method is for defining equality of two objects.<\/p>\r\n\r\n\r\n\r\n<p>The benefit of going this way is that you can sort your array of custom type objects anywhere in your Swift project without passing in sorting logic anymore.<\/p>\r\n\r\n\r\n\r\n<p>In the following you see an implementation for a custom type <code>RowModel<\/code> that has an optional <code>Date<\/code> property. In this case, I added an additional method for unwrapping and comparing the two arguments. If your <code>date<\/code> property is not optional you would not need that.<\/p>\r\n\r\n\r\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Swift\" data-shcb-language-slug=\"swift\"><span><code class=\"hljs language-swift\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">extension<\/span> <span class=\"hljs-title\">RowModel<\/span>: <span class=\"hljs-title\">Comparable<\/span> <\/span>{\r\n\t<span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> &lt; (lhs: RowModel, rhs: RowModel) -&gt; <span class=\"hljs-title\">Bool<\/span> <\/span>{\r\n\t\t<span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">let<\/span> result = compare(lhs, rhs), result == .orderedAscending {\r\n\t\t\t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">true<\/span>\r\n\t\t}\r\n\t\t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>\r\n\t}\r\n\r\n\t<span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> == <span class=\"hljs-params\">(lhs: RowModel, rhs: RowModel)<\/span><\/span> -&gt; <span class=\"hljs-type\">Bool<\/span> {\r\n\t\t<span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">let<\/span> result = compare(lhs, rhs), result == .orderedSame {\r\n\t\t\t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">true<\/span>\r\n\t\t}\r\n\t\t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>\r\n\t}\r\n\r\n\t<span class=\"hljs-keyword\">fileprivate<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">func<\/span> <span class=\"hljs-title\">compare<\/span><span class=\"hljs-params\">(<span class=\"hljs-number\">_<\/span> lhs: RowModel, <span class=\"hljs-number\">_<\/span> rhs: RowModel)<\/span><\/span> -&gt; <span class=\"hljs-type\">ComparisonResult?<\/span> {\r\n\t\t<span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-keyword\">let<\/span> lhsDate = lhs.date,\r\n\t\t   <span class=\"hljs-keyword\">let<\/span> rhsDate = rhs.date {\r\n\t\t\t<span class=\"hljs-keyword\">return<\/span> lhsDate.compare(rhsDate)\r\n\t\t}\r\n\t\t<span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">nil<\/span>\r\n\t}\r\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Swift<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">swift<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\r\n\r\n\r\n<p>With this small addition you can shorten your calls for sorting an array to this:<\/p>\r\n\r\n\r\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/\/ Sort for descending order<\/span>\r\nsomeArray.sort(&gt;)\r\n\r\n<span class=\"hljs-comment\">\/\/ Sort for ascending order<\/span>\r\nsomeArray.sort()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>","protected":false},"excerpt":{"rendered":"<p>You might know the very handy sort(by:) method in Swift that you can use to sort any kind of array. If not, see this as some kind of friendly introduction to you. Read carefully and I will teach you now how to sort an array of custom type objects by their date property \ud83d\ude42 The&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[3],"tags":[4,35],"class_list":["post-377","post","type-post","status-publish","format-standard","hentry","category-ios-development","tag-ios","tag-swift"],"_links":{"self":[{"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/posts\/377","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/comments?post=377"}],"version-history":[{"count":6,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/posts\/377\/revisions"}],"predecessor-version":[{"id":410,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/posts\/377\/revisions\/410"}],"wp:attachment":[{"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/media?parent=377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/categories?post=377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mic.st\/blog\/wp-json\/wp\/v2\/tags?post=377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}