{"post": {"oid": "sort-a-javascript-array-by-some-boolean-operation", "title": "Sort a JavaScript array by some boolean operation", "body": "<p><strong>UPDATE Feb 4, 2022</strong> Yes, as commenter Matthias pointed out, you can let JavaScript implicitly make the conversion of boolean minus boolean to end number a number of -1, 0, or 1.</p>\n<p>Original but edited blog post below...</p>\n<hr />\n<p>Imagine you have an array like this:</p>\n<pre><code class=\"hljs\">\n<span class=\"hljs-keyword\">const</span> items = [\n  { <span class=\"hljs-attr\">num</span>: <span class=\"hljs-string\">&#x27;one&#x27;</span>, <span class=\"hljs-attr\">labels</span>: [] },\n  { <span class=\"hljs-attr\">num</span>: <span class=\"hljs-string\">&#x27;two&#x27;</span>, <span class=\"hljs-attr\">labels</span>: [<span class=\"hljs-string\">&#x27;foo&#x27;</span>] },\n  { <span class=\"hljs-attr\">num</span>: <span class=\"hljs-string\">&#x27;three&#x27;</span>, <span class=\"hljs-attr\">labels</span>: [<span class=\"hljs-string\">&#x27;bar&#x27;</span>] },\n  { <span class=\"hljs-attr\">num</span>: <span class=\"hljs-string\">&#x27;four&#x27;</span>, <span class=\"hljs-attr\">labels</span>: [<span class=\"hljs-string\">&#x27;foo&#x27;</span>] },\n  { <span class=\"hljs-attr\">num</span>: <span class=\"hljs-string\">&#x27;five&#x27;</span>, <span class=\"hljs-attr\">labels</span>: [] },\n];\n</code></pre>\n\n<p>What you want, is to sort them in a way that all those entries that have a label <code>foo</code> come first, but you don't want to \"disturb\" the existing order. Essentially you want this to be the end result:</p>\n<pre>{ num: &#x27;two&#x27;, labels: [&#x27;foo&#x27;] },\n{ num: &#x27;four&#x27;, labels: [&#x27;foo&#x27;] },\n\n{ num: &#x27;one&#x27;, labels: [] },\n{ num: &#x27;three&#x27;, labels: [&#x27;bar&#x27;] },\n{ num: &#x27;five&#x27;, labels: [] },</pre>\n\n<p>Here's a way to do that:</p>\n<pre><code class=\"hljs\">\nitems.<span class=\"hljs-title function_\">sort</span>(\n  <span class=\"hljs-function\">(<span class=\"hljs-params\">itemA, itemB</span>) =&gt;</span>\n    itemB.<span class=\"hljs-property\">labels</span>.<span class=\"hljs-title function_\">includes</span>(<span class=\"hljs-string\">&#x27;foo&#x27;</span>) - itemA.<span class=\"hljs-property\">labels</span>.<span class=\"hljs-title function_\">includes</span>(<span class=\"hljs-string\">&#x27;foo&#x27;</span>)\n);\n<span class=\"hljs-variable language_\">console</span>.<span class=\"hljs-title function_\">log</span>(items);\n</code></pre>\n\n<p>And the outcome is:</p>\n<pre>[\n  { num: &#x27;two&#x27;, labels: [ &#x27;foo&#x27; ] },\n  { num: &#x27;four&#x27;, labels: [ &#x27;foo&#x27; ] },\n  { num: &#x27;one&#x27;, labels: [] },\n  { num: &#x27;three&#x27;, labels: [ &#x27;bar&#x27; ] },\n  { num: &#x27;five&#x27;, labels: [] }\n]</pre>\n\n<p><s>The simple trick is to turn then test operation into a number (0 or 1) and you can do that with <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number\"><code>Number</code></a>.</s></p>\n<p>Boolean minus boolean is operator overloaded to become an integer. From the Node repl...</p>\n<pre>&gt; true - false\n1\n&gt; false - true\n-1\n&gt; false - false\n0\n&gt; true - true\n0</pre>", "pub_date": "2021-12-02T15:09:15.617Z", "open_graph_image": "/cache/bd/23/bd23a05915cee89697e25bcea6b167a4.png", "url": null, "summary": "", "categories": ["JavaScript"], "disallow_comments": false, "hide_comments": false, "previous_post": {"oid": "brotli-compression-quality-comparison-in-the-real-world", "title": "Brotli compression quality comparison in the real world", "pub_date": "2021-12-01T13:15:34.304Z", "categories": ["Node", "JavaScript"]}, "next_post": {"oid": "my-sites-now-nextjs", "title": "My site's now NextJS - And I (almost) regret it already", "pub_date": "2021-12-17T15:05:14.727Z", "categories": ["Django", "Node", "React", "JavaScript"]}, "related_by_category": [{"oid": "always-run-biome-migrate-after-upgrading-biome", "title": "Always run biome migrate after upgrading biome", "pub_date": "2025-08-16T16:08:34.161Z", "categories": ["JavaScript"]}, {"oid": "video-to-screenshots-app", "title": "Video to Screenshots app", "pub_date": "2025-06-21T22:43:46.320Z", "categories": ["JavaScript"]}, {"oid": "how-to-handle-success-and-failure-usequery-hook", "title": "How to handle success and failure in @tanstack/react-query useQuery hook", "pub_date": "2024-09-16T10:27:38.290Z", "categories": ["JavaScript"]}, {"oid": "ideal-pattern-react-router-with-tanstackreact-query", "title": "An ideal pattern to combine React Router with TanStack Query", "pub_date": "2024-11-18T16:20:15.909Z", "categories": ["JavaScript"]}], "related_by_keyword": [{"oid": "sort-case-insensitively-empty-strings-last-django", "title": "How to sort case insensitively with empty strings last in Django", "pub_date": "2022-04-03T19:34:51.665Z", "categories": ["Python", "Django", "PostgreSQL"]}, {"oid": "find-the-largest-node_modules-directories", "title": "Find the largest node_modules directories with bash", "pub_date": "2022-09-30T23:30:24.982Z", "categories": ["Linux", "Bash", "macOS"]}, {"oid": "how-to-count-the-most-common-lines-in-a-file", "title": "How to count the most common lines in a file", "pub_date": "2022-10-07T16:20:35.507Z", "categories": ["Linux", "Bash", "macOS"]}, {"oid": "in-python-you-sort-with-a-tuple", "title": "In Python you sort with a tuple", "pub_date": "2013-06-14T01:34:53Z", "categories": ["Python"]}]}, "comments": {"truncated": false, "count": 2, "total_pages": 1, "tree": [{"id": 35628, "oid": "c8a6cba", "add_date": "2022-02-03T07:14:57.311Z", "name": "Matthias", "comment": "Hi there!<br><br>Instead of using Number() on both includes-results, you can just use \"itemB.labels.includes('foo') - itemA.labels.includes('foo')\".<br><br>This works because minus will convert both sides to a number anyway before subtracting.<br><br>Best regards", "approved": true, "depth": 0, "replies": [{"id": 35635, "oid": "c747143", "add_date": "2022-02-04T12:21:52.136Z", "name": "mail@peterbe.com", "comment": "You're right! I had forgotten about that. I updated the blog post. <br>Truth be told, I'm not sure it's an improvement because it feels like a quirk whereas casting to a number type feels a bit more \"commonstream\".", "approved": true, "depth": 1}]}], "next_page": null, "previous_page": null}}