Print

Sort an associative array by values in Javascript

What?
An article on how to quickly adapt an array code and sort by its values. Surprising how many examples are on the web and everyone saying you're doing it wrong... Which is true but quite unhelpful. The original code is not my own either but that's not an excuse. I also found that examples across the web were only partial and thought I'd write a full example here. No jQuery and using the Google Chrome browser. I wanted to:
  1. Sort the array by its values
    copyraw
    my_records.sort();
    1.  my_records.sort()
  2. Iterate through and output these in HTML
    copyraw
    for(i=0;i<my_records.length;i++){
            // do something to my_records[i]
    }
    1.  for(i=0;i<my_records.length;i++){ 
    2.          // do something to my_records[i] 
    3.  } 

What I have:
copyraw
var my_records = new Array();
        my_records["item1"] = "My Value 2";
        my_records["item2"] = "My Value 3";
        my_records["item3"] = "My Value 1";

        document.write('<option value="item1">My Value 2</option>');
        document.write('<option value="item2">My Value 3</option>');
        document.write('<option value="item3">My Value 1</option>');
  1.  var my_records = new Array()
  2.          my_records["item1"] = "My Value 2"
  3.          my_records["item2"] = "My Value 3"
  4.          my_records["item3"] = "My Value 1"
  5.   
  6.          document.write('<option value="item1">My Value 2</option>')
  7.          document.write('<option value="item2">My Value 3</option>')
  8.          document.write('<option value="item3">My Value 1</option>')
What I want:
copyraw
var my_records = new Array();
        my_records["item3"] = "My Value 1";
        my_records["item1"] = "My Value 2";
        my_records["item2"] = "My Value 3";

        document.write('<option value="item3">My Value 1</option>');
        document.write('<option value="item1">My Value 2</option>');
        document.write('<option value="item2">My Value 3</option>');
  1.  var my_records = new Array()
  2.          my_records["item3"] = "My Value 1"
  3.          my_records["item1"] = "My Value 2"
  4.          my_records["item2"] = "My Value 3"
  5.   
  6.          document.write('<option value="item3">My Value 1</option>')
  7.          document.write('<option value="item1">My Value 2</option>')
  8.          document.write('<option value="item2">My Value 3</option>')

Why?
I could give my client a condescending lesson on the semantics of javascript 'associative arrays' and just say it's not possible, they should get their datasource ordered... Or I can say 'Of course it's possible!' and just tweak their code ever so slightly.

How?
A lot of examples out there use numbers which makes the task easier. I'm the type of idiot that volunteers first and asks for details afterwards. I get the task to sort by string values.

Note: This has been adapted to work when using the Google Chrome browser (at time of print: Version 45.0.2454.101 m).

Method #1: Convert to JSON then split string
Changing as little as possible to the customer's code, we need to find&replace their datasource code:
copyraw
// replace 'new Array();'       with "["                // open square bracket
        // replace 'my_records["'       with "{ myKey: '"
        // replace '"] = "'             with "', myValue: '"    
        // replace '";'                 with "' },"             // omit comma for the last element

        // yielding:
        var my_records = [
                { myKey: 'item1', myValue: 'My Value 2' },
                { myKey: 'item2', myValue: 'My Value 3' },
                { myKey: 'item3', myValue: 'My Value 1' }
        ]

        // make copy of my_records array/object
        var my_records_copy = my_records.slice(0);      

        // sorts the array by myValue (string)
        my_records_copy.sort(function(a,b) {
                var x = a.myValue.toLowerCase();
                var y = b.myValue.toLowerCase();
                return x < y ? -1 : x > y ? 1 : 0;
        });

        // use built-in JSON stringify function
        newSortedArrayObject = JSON.stringify(my_records_copy);  // note: will convert single apostrophes to double-quotes

        // split by closing curly brace
        var myRecords = newSortedArrayObject.split('}');

        // removes last row which is undefined (ie. "]")
        myRecords.pop();  

        // loop through array
        for (i=0; i<myRecords.length; i++){

                // split the record where double-quote is the delimiter
                var thisRecord = myRecords[i].split('"');

                // output
                document.write('<option value="' + thisRecord[3] + '">' + thisRecord[7] + '</option>');
        }
  1.  // replace 'new Array();'       with "["                // open square bracket 
  2.          // replace 'my_records["'       with "{ myKey: '" 
  3.          // replace '"] = "'             with "', myValue: '" 
  4.          // replace '";'                 with "' },"             // omit comma for the last element 
  5.   
  6.          // yielding: 
  7.          var my_records = [ 
  8.                  { myKey: 'item1', myValue: 'My Value 2' }, 
  9.                  { myKey: 'item2', myValue: 'My Value 3' }, 
  10.                  { myKey: 'item3', myValue: 'My Value 1' } 
  11.          ] 
  12.   
  13.          // make copy of my_records array/object 
  14.          var my_records_copy = my_records.slice(0)
  15.   
  16.          // sorts the array by myValue (string) 
  17.          my_records_copy.sort(function(a,b) { 
  18.                  var x = a.myValue.toLowerCase()
  19.                  var y = b.myValue.toLowerCase()
  20.                  return < y ? -1 : x > y ? 1 : 0
  21.          })
  22.   
  23.          // use built-in JSON stringify function 
  24.          newSortedArrayObject = JSON.stringify(my_records_copy);  // note: will convert single apostrophes to double-quotes 
  25.   
  26.          // split by closing curly brace 
  27.          var myRecords = newSortedArrayObject.split('}')
  28.   
  29.          // removes last row which is undefined (ie. "]") 
  30.          myRecords.pop()
  31.   
  32.          // loop through array 
  33.          for (i=0; i<myRecords.length; i++){ 
  34.   
  35.                  // split the record where double-quote is the delimiter 
  36.                  var thisRecord = myRecords[i].split('"')
  37.   
  38.                  // output 
  39.                  document.write('<option value="' + thisRecord[3] + '">' + thisRecord[7] + '</option>')
  40.          } 

Other Methods?
Bearing in mind that I needed to sort by the values and then output in HTML format using Google Chrome, the above is the only method I could actually get working, and leave it in an understandable manner for my customers. Other sources I browsed before working out this solution:
Category: JavaScript :: Article: 632