Matt Kent
Matt Kent

Reputation: 1185

JS sort is not a function

I'm currently attempting to sort an object although I've been facing a data.sort is not a function error.

I have taken inspiration from the following StackOverflow answer: Sort Table by click in header tag regardless of it is numeric, alphabetical or date.

I have also had a browse of other questions and haven't yet managed to fix my issue, as it tends to lead to other issues such as the value being undefined.

Here is my object:

{
    "2010-01": {
        "item1": 324,
        "item2": 1075,
        "item3": 940,
        "item4": 441,
        "item5": 1040,
        "item6": 898,
        "item7": 1343
    },
    "2011-02": {
        "item1": 295,
        "item2": 958,
        "item3": 904,
        "item4": 434,
        "item5": 1038,
        "item6": 793,
        "item7": 1246
    },
    "2012-03": {
        "item1": 314,
        "item2": 1062,
        "item3": 980,
        "item4": 494,
        "item5": 1158,
        "item6": 914,
        "item7": 1461
    },
    "2008-04": {
        "item1": 336,
        "item2": 1022,
        "item3": 987,
        "item4": 488,
        "item5": 1014,
        "item6": 792,
        "item7": 1382
    },
    "2007-05": {
        "item1": 332,
        "item2": 1073,
        "item3": 1002,
        "item4": 512,
        "item5": 1104,
        "item6": 840,
        "item7": 1368
    },
    "2005-06": {
        "item1": 311,
        "item2": 981,
        "item3": 837,
        "item4": 432,
        "item5": 1002,
        "item6": 801,
        "item7": 1265
    },
    "2014-07": {
        "item1": 321,
        "item2": 1049,
        "item3": 921,
        "item4": 489,
        "item5": 963,
        "item6": 881,
        "item7": 1340
    },
    "2015-08": {
        "item1": 294,
        "item2": 1071,
        "item3": 960,
        "item4": 506,
        "item5": 910,
        "item6": 885,
        "item7": 1312
    },
    "2016-09": {
        "item1": 281,
        "item2": 1020,
        "item3": 952,
        "item4": 502,
        "item5": 1068,
        "item6": 914,
        "item7": 1397
    },
    "2009-10": {
        "item1": 319,
        "item2": 1058,
        "item3": 985,
        "item4": 546,
        "item5": 1184,
        "item6": 1031,
        "item7": 1448
    },
    "2005-11": {
        "item1": 300,
        "item2": 1021,
        "item3": 967,
        "item4": 474,
        "item5": 1176,
        "item6": 1009,
        "item7": 1387
    },
    "2017-12": {
        "item1": 307,
        "item2": 1027,
        "item3": 924,
        "item4": 427,
        "item5": 1024,
        "item6": 844,
        "item7": 1300
    }
}

My function for sorting, which at the minute I've only started by trying order the first item in either ascending or descending order.

function sortData(key, data, type) {
        if (key === "item1") {
          if (type === "asc") {
            data.sort(function(a, b) {
              return a[key] > b[key];
            });
          } else {
            data.sort(function(a, b) {
              return a[key] < b[key];
            });
          }
        }
        return data;
      }

The data is the object, and I've tried to pass it like such: sortData('item1', [data], 'asc'); as opposed to just data but with no luck. If someone could shed some light as to what I'm doing wrong that would be great.

Upvotes: 4

Views: 16987

Answers (3)

CaptainGenesisX
CaptainGenesisX

Reputation: 405

I had the same problem. I made the mistake of storing two combined arrays in a string and then trying to use the sort method. Try this:

if (charSelected == "all") 
    {
        charArray = heroes.concat(villains).sort();

    }

Upvotes: 0

Ele
Ele

Reputation: 33726

This approach uses Arrow functions and reduce function.

It's a little shorter.

let data = { "2010-01": { "item1": 324, "item2": 1075, "item3": 940, "item4": 441, "item5": 1040, "item6": 898, "item7": 1343 }, "2011-02": { "item1": 295, "item2": 958, "item3": 904, "item4": 434, "item5": 1038, "item6": 793, "item7": 1246 }, "2012-03": { "item1": 314, "item2": 1062, "item3": 980, "item4": 494, "item5": 1158, "item6": 914, "item7": 1461 }, "2008-04": { "item1": 336, "item2": 1022, "item3": 987, "item4": 488, "item5": 1014, "item6": 792, "item7": 1382 }, "2007-05": { "item1": 332, "item2": 1073, "item3": 1002, "item4": 512, "item5": 1104, "item6": 840, "item7": 1368 }, "2005-06": { "item1": 311, "item2": 981, "item3": 837, "item4": 432, "item5": 1002, "item6": 801, "item7": 1265 }, "2014-07": { "item1": 321, "item2": 1049, "item3": 921, "item4": 489, "item5": 963, "item6": 881, "item7": 1340 }, "2015-08": { "item1": 294, "item2": 1071, "item3": 960, "item4": 506, "item5": 910, "item6": 885, "item7": 1312 }, "2016-09": { "item1": 281, "item2": 1020, "item3": 952, "item4": 502, "item5": 1068, "item6": 914, "item7": 1397 }, "2009-10": { "item1": 319, "item2": 1058, "item3": 985, "item4": 546, "item5": 1184, "item6": 1031, "item7": 1448 }, "2005-11": { "item1": 300, "item2": 1021, "item3": 967, "item4": 474, "item5": 1176, "item6": 1009, "item7": 1387 }, "2017-12": { "item1": 307, "item2": 1027, "item3": 924, "item4": 427, "item5": 1024, "item6": 844, "item7": 1300 } };
// ----------------
let byThis = 'item1';
let compare = (k, kk) => data[k][byThis] - data[kk][byThis];

let sorted = Object.keys(data).sort(compare).reduce((a, d) => ({ ...a, ...{ [d]: data[d] } }), {});

console.log(sorted);
.as-console-wrapper {
  max-height: 100% !important
}

Upvotes: 2

mdatsev
mdatsev

Reputation: 3879

The problem is that the data is not an array and sort is an array method. You can use Object.keys to get an array of the keys, sort that and then populate with the values with a forEach:

let unsorted_data = { "2010-01": { "item1": 324, "item2": 1075, "item3": 940, "item4": 441, "item5": 1040, "item6": 898, "item7": 1343 }, "2011-02": { "item1": 295, "item2": 958, "item3": 904, "item4": 434, "item5": 1038, "item6": 793, "item7": 1246 }, "2012-03": { "item1": 314, "item2": 1062, "item3": 980, "item4": 494, "item5": 1158, "item6": 914, "item7": 1461 }, "2008-04": { "item1": 336, "item2": 1022, "item3": 987, "item4": 488, "item5": 1014, "item6": 792, "item7": 1382 }, "2007-05": { "item1": 332, "item2": 1073, "item3": 1002, "item4": 512, "item5": 1104, "item6": 840, "item7": 1368 }, "2005-06": { "item1": 311, "item2": 981, "item3": 837, "item4": 432, "item5": 1002, "item6": 801, "item7": 1265 }, "2014-07": { "item1": 321, "item2": 1049, "item3": 921, "item4": 489, "item5": 963, "item6": 881, "item7": 1340 }, "2015-08": { "item1": 294, "item2": 1071, "item3": 960, "item4": 506, "item5": 910, "item6": 885, "item7": 1312 }, "2016-09": { "item1": 281, "item2": 1020, "item3": 952, "item4": 502, "item5": 1068, "item6": 914, "item7": 1397 }, "2009-10": { "item1": 319, "item2": 1058, "item3": 985, "item4": 546, "item5": 1184, "item6": 1031, "item7": 1448 }, "2005-11": { "item1": 300, "item2": 1021, "item3": 967, "item4": 474, "item5": 1176, "item6": 1009, "item7": 1387 }, "2017-12": { "item1": 307, "item2": 1027, "item3": 924, "item4": 427, "item5": 1024, "item6": 844, "item7": 1300 } };

function sortData(key, data, type) {
  let ordered = {};
  let compareFunction = function(a, b) {
    return data[b][key] - data[a][key];
  };
  if (type === "asc") {
    compareFunction = function(a, b) {
      return data[a][key] - data[b][key];
    }
  }
  Object.keys(data).sort(compareFunction).forEach(function(key) {
    ordered[key] = data[key];
  });
  return ordered;
}


console.log(sortData("item1", unsorted_data, 'asc'));

And you can still pass your custom compare functions for asc and desc. order to sort, but I have omitted that for simplicity.

Upvotes: 7

Related Questions