0

I am working to sort an array of objects in descending order using pure javascript. I initially thought that a JSON.stringify method was causing the issue, as described [here][1]. Apparently JSON.stringify does not preserve the order of objects by design. Give the below array of objects I seem to get a random sort order using the following code where I sort the array of objects and then derive the weight property of the first object in the array.

var byWeight = objArray.slice(0);
var sorted = byWeight.sort(function(a,b) { return b.weight - a.weight; } );
sorted[0].something.weight;

On distinct runs of this code, I seem to randomly derive .29 or .35 for the weight. Why is this occurring?

Here is the array:

[
  {
    "something": {
      "terms": [
        {
          "elements": {
            "number": {
              "span": [
                9,
                10
              ],
              "value": "1"
            }
          },
          "span": [
            9,
            12
          ],
          "value": "1g",
          "label": "grams"
        }
      ],
      "span": [
        9,
        12
      ],
      "weight": 0.29,
      "value": "1gm"
    }
  },
  {
    "something": {
      "terms": [
        {
          "elements": {
            "number": {
              "span": [
                16,
                18
              ],
              "value": "30"
            }
          },
          "span": [
            16,
            20
          ],
          "value": "30ml",
          "label": "liters"
        }
      ],
      "span": [
        16,
        20
      ],
      "weight": 0.35,
      "value": "30ml"
    }
  }
]
dtburgess
  • 551
  • 4
  • 16
  • 4
    Looks to me as if it should be `b.something.weight - a.something.weight` – Pointy Aug 25 '15 at 14:22
  • Separately: *"Apparently JSON.stringify does not preserve the order of objects"*. It can't. [Javascript object properties don't *have* an order to preserve](http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order), – Paul Roub Aug 25 '15 at 14:27
  • Your objArray is poorly formatted, "terms" shouldn't be an array if it contains key-indexed elements like "span", "value", and "label' it should be an object. it works fine if you change that: http://jsfiddle.net/s4k3t1Lo/ – JKirchartz Aug 25 '15 at 14:27
  • @JKirchartz Correct objArray. error was introduced during simplification for presentation here. - OP – dtburgess Aug 25 '15 at 14:39

2 Answers2

1

You have the wrong reference. Change this

var sorted = byWeight.sort(function(a,b) { return b.weight - a.weight; } );

to (watch .something.)

byWeight.sort(function (a, b) { return b.something.weight - a.something.weight; });

Working model:

var data = [
  {
      "something": {
          "terms": {
              "span": [
              9,
              12
              ],
              "value": "1g",
              "label": "grams"
          }
      ,
          "span": [
          9,
          12
          ],
          "weight": 0.29,
          "value": "1gm"
      }
  },
  {
      "something": {
          "terms": {
              "span": [
              16,
              20
              ],
              "value": "30ml",
              "label": "liters"
          }
      ,
          "span": [
          16,
          20
          ],
          "weight": 0.35,
          "value": "30ml"
      }
  }
];

var sorted = data.slice(0);
sorted.sort(function (a, b) {
    return b.something.weight - a.something.weight; // desc!
});
document.write('<pre>' + JSON.stringify(sorted, 0, 4) + '</pre>');
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
  • Not quite. I need it in descending order. But you were half right in that I was omitting "something" from "return a.something.weight - b.something.weight" So this works: "byWeight.sort(function (a, b) { return b.something.weight - a.something.weight; });" – dtburgess Aug 25 '15 at 14:49
  • I don't think you should have deleted the explanation. – dtburgess Aug 25 '15 at 14:58
0

Your objArray is poorly formatted, "terms" shouldn't be an array if it contains key-indexed elements like "span", "value", and "label' it should be an object; then your sort is looking in the wrong place, it should be looking at a.something.weight/b.something.weight instead. jsfiddle.net/3qgtn9r1

var objArray = [
  {
    "something": {
      "terms": {
          "span": [
            9,
            12
          ],
          "value": "1g",
          "label": "grams"
      },
      "span": [
        9,
        12
      ],
      "weight": 0.29,
      "value": "1gm"
    }
  },
  {
    "something": {
      "terms": {
          "span": [
            16,
            20
          ],
          "value": "30ml",
          "label": "liters"
      },
      "span": [
        16,
        20
      ],
      "weight": 0.35,
      "value": "30ml"
    }
  }
];
var byWeight = objArray.slice(0);
var sorted = byWeight.sort(function(a,b) { return a.something.weight - b.something.weight; } );
console.log(sorted[0].something.weight);
JKirchartz
  • 15,862
  • 7
  • 54
  • 82