title: Javascript Sort array of objects for a sub-key of an object
body: <p>I have an array of objects that I need to sort in javascript (es6 is fine), or jquery. The data is a bit more complicated than a regular array of objects because the value is located in a sub-object. I need to sort for a dynamic key where the data to sort on is located in an object of the dynamic key. For example I need to sort 'id' ascending or descending and the data is located in id.data.</p>
  
  <pre><code>    [{
      "_row": {},
      "_parent": {},
      "id": {"data": 112, "cell": {}},
      "name": {"data": "D'Amore, Volkman and Cole", "cell": {}},
      "check_name": {"data": "", "cell": {}},
      "account_number": {"data": "5534867831801846", "cell": {}},
      "main_email": {"data": "akovacek@yahoo.com", "cell": {}},
      "cc_email": {"data": "cupton@gmail.com", "cell": {}},
      "main_phone": {"data": "1-845-550-6422", "cell": {}},
      "work_phone": {"data": "+1 (859) 399-6372", "cell": {}},
      "mobile": {"data": "292-242-7626 x798", "cell": {}},
      "fax": {"data": "", "cell": {}},
      "active": {"data": 1, "cell": {}},
      "billing_address": {"data": "24226 Mackenzie Junctions Suite 393\nDonaldside, GA 87531", "cell": {}},
      "shipping_address": {"data": "478 Toy Loaf Suite 552\nWaelchiberg, ND 70701-3633", "cell": {}},
      "comments": {"data": "", "cell": {}}
  }, {
      "_row": {},
      "_parent": {},
      "id": {"data": 120, "cell": {}},
      "name": {"data": "Carroll, Rice and Reilly", "cell": {}},
      "check_name": {"data": "", "cell": {}},
      "account_number": {"data": "4539358256447", "cell": {}},
      "main_email": {"data": "ocie.ebert@bergstrom.net", "cell": {}},
      "cc_email": {"data": "bmoen@kshlerin.info", "cell": {}},
      "main_phone": {"data": "612-864-9512", "cell": {}},
      "work_phone": {"data": "(519) 761-1805", "cell": {}},
      "mobile": {"data": "+1-730-669-4339", "cell": {}},
      "fax": {"data": "", "cell": {}},
      "active": {"data": 1, "cell": {}},
      "billing_address": {"data": "848 Rashawn Causeway\nHauckberg, GA 21193", "cell": {}},
      "shipping_address": {"data": "3458 Wolff Cape Suite 336\nWolfmouth, DC 35821", "cell": {}},
      "comments": {"data": "", "cell": {}}
  }, {
      "_row": {},
      "_parent": {},
      "id": {"data": 122, "cell": {}},
      "name": {"data": "Denesik and Sons", "cell": {}},
      "check_name": {"data": "", "cell": {}},
      "account_number": {"data": "6011079688853496", "cell": {}},
      "main_email": {"data": "clinton41@schiller.com", "cell": {}},
      "cc_email": {"data": "daron80@corwin.info", "cell": {}},
      "main_phone": {"data": "569-382-2580 x1764", "cell": {}},
      "work_phone": {"data": "705.782.2219", "cell": {}},
      "mobile": {"data": "936-586-1978", "cell": {}},
      "fax": {"data": "", "cell": {}},
      "active": {"data": 1, "cell": {}},
      "billing_address": {"data": "1864 Donnelly Parkway Suite 222\nPort Hailieburgh, NC 08808-0938", "cell": {}},
      "shipping_address": {"data": "28476 Jerald Valleys Apt. 537\nNorth Vancemouth, DC 16865-0793", "cell": {}},
      "comments": {"data": "", "cell": {}}
  }, {
      "_row": {},
      "_parent": {},
      "id": {"data": 124, "cell": {}},
      "name": {"data": "Trantow, Botsford and Runolfsson", "cell": {}},
      "check_name": {"data": "", "cell": {}},
      "account_number": {"data": "4556163511909216", "cell": {}},
      "main_email": {"data": "jordane77@adams.com", "cell": {}},
      "cc_email": {"data": "shawn34@block.info", "cell": {}},
      "main_phone": {"data": "+16989316200", "cell": {}},
      "work_phone": {"data": "969.610.8041 x8593", "cell": {}},
      "mobile": {"data": "680.717.5368", "cell": {}},
      "fax": {"data": "", "cell": {}},
      "active": {"data": 1, "cell": {}},
      "billing_address": {"data": "96778 VonRueden Square Suite 421\nKennafort, SC 70938", "cell": {}},
      "shipping_address": {"data": "13334 Orion Green\nEast Lillieborough, ND 19714", "cell": {}},
      "comments": {"data": "", "cell": {}}
  }]
  </code></pre>
  
  <p>The next step of complication is that I would like to sort by id, then another key, like active, then name, etc.</p>
  
  <p>Any Ideas? Can I harness <code>.sort</code>?
  (it looks like I am not using the cell object, maybe I can remove that to make my life easier. I think I added it for a very important reason years ago)</p>
  
  <p>Here is an update to what I had figured out.. the first sort works fine, sorting multiple columns does not appear to be working.</p>
  
  <p>attempt 1:</p>
  
  <pre><code>        //sort_array looks like [{db_field:'asc'},etc...]
      //we need to sort row based on data for this.tdo[row][db_filed]['data']
      this.tdo.sort((a,b) =&gt; {
          sort_array.forEach(sort =&gt; {
              let keys = Object.keys(sort);
              let name = keys[0];
              if(sort[keys[0]] =='asc')
              {
                  this.tdo = this.tdo.sort(this.dynamicSort(name));
              }
              else
              {
                  this.tdo = this.tdo.sort(this.dynamicSort('-'+name));
              }
          })
  
      })
  </code></pre>
  
  <p>where <code>dynamicSort</code> was pulled from stack overflow <a href="https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript">Sort array of objects by string property value in JavaScript</a></p>
  
  <pre><code>dynamicSort(property) {
      let sortOrder = 1;
      if (property[0] === "-") {
          sortOrder = -1;
          property = property.substr(1);
      }
      return function (a, b) {
          let result = (a[property].data &lt; b[property].data) ? -1 : (a[property].data &gt; b[property].data) ? 1 : 0;
          return result * sortOrder;
      }
  }
  </code></pre>
  
  <p>attempt 2 , using <a href="https://github.com/Teun/thenBy.js" rel="nofollow noreferrer">thenBy</a> which is pretty cool. I found an example how to stack sorting in their closed issues:</p>
  
  <pre><code> let sort_stack = firstBy(function (v1, v2) { return 0 });
      sort_array.forEach(sort =&gt; {
          let keys = Object.keys(sort);
          let name = keys[0];
          if(sort[keys[0]] =='asc')
          {
              sort_stack = sort_stack.thenBy(function (v1) { return v1[name].data; });
          }
          else
          {
              sort_stack = sort_stack.thenBy(function (v1) { return v1[name].data ; },-1);
          }
      })
  
      this.tdo.sort(sort_stack);
  </code></pre>
  
  <p>Additionally I may need to restrict user input sub-sorting based on the type of data... as columns like <code>id</code> will sort only once</p>
  
  <p>Not sure why I got a down vote, this sort is pretty complicated and beyond the scope of the <code>.sort</code> documentation</p>