0

I have an Array i will Like to sort with a field in the array But its not working

var data = [{tm: "09:00", tr: "30.34", rd: "73.23"},
{tm: "09:10", tr: "30.45", rd: "70.77"},
{tm: "09:50", tr: "29.95", rd: "75.70"},
{tm: "09:40", tr: "29.95", rd: "75.70"},
{tm: "01:50", tr: "29.95", rd: "75.70"},
{tm: "02:30", tr: "29.95", rd: "75.70"},
{tm: "04:50", tr: "29.95", rd: "75.70"},
{tm: "10:00", tr: "30.05", rd: "76.20"}];

i need to sort it with the tm field so the data will be in this format after sorting

0 tm: 01.50
1 tm: 02.30
2 tm: 04.50
3 tm: 09.00
4 tm: 09.10
5 tm: 09.40
6 tm: 09.50
7 tm: 10.00

i tried

data.sort(function(a, b){return a.tm - b.tm});

its not working Any help will be appreciated Thanks

Donsplash
  • 23
  • 6

3 Answers3

3

HH:MM is intrinsically sort-able, so passing to localeCompare will work as expected.

var data = [{tm: "09:00", tr: "30.34", rd: "73.23"},
{tm: "09:10", tr: "30.45", rd: "70.77"},
{tm: "09:50", tr: "29.95", rd: "75.70"},
{tm: "09:40", tr: "29.95", rd: "75.70"},
{tm: "01:50", tr: "29.95", rd: "75.70"},
{tm: "02:30", tr: "29.95", rd: "75.70"},
{tm: "04:50", tr: "29.95", rd: "75.70"},
{tm: "10:00", tr: "30.05", rd: "76.20"}];

data.sort((a, b) => a.tm.localeCompare(b.tm));

console.log(data)
Keith
  • 22,005
  • 2
  • 27
  • 44
  • 1
    Great use of `localeCompare`! Every time I see `locale` methods I get a little excited because they do seem to take care of common issues. Problem is that I hardly ever think of them. – zfrisch Apr 23 '19 at 16:23
2

a.tm - b.tm would work if they are numbers. Because of : between them, "09:10" - "09:50" returns NaN.

So, You could replace the : and get just the numbers before subtracting tm values

var data = [
    { tm: "09:00", tr: "30.34", rd: "73.23" },
    { tm: "09:10", tr: "30.45", rd: "70.77" },
    { tm: "09:50", tr: "29.95", rd: "75.70" },
    { tm: "09:40", tr: "29.95", rd: "75.70" },
    { tm: "01:50", tr: "29.95", rd: "75.70" },
    { tm: "02:30", tr: "29.95", rd: "75.70" },
    { tm: "04:50", tr: "29.95", rd: "75.70" },
    { tm: "10:00", tr: "30.05", rd: "76.20" }
  ];

data.sort((a, b) => +a.tm.replace(":", '') - +b.tm.replace(":", ''))

console.log(data)
adiga
  • 34,372
  • 9
  • 61
  • 83
  • 1
    Careful if you have any values around midnight, such as `00:10` - You wouldn't want `00:10` to evaluate as `>` `09:00` – Lewis Apr 23 '19 at 13:27
  • Nice solution. I'll have to keep that one in mind for time calculations. – zfrisch Apr 23 '19 at 13:28
  • This is definitely very hacky. And you didnt include any explanation about why you are doing that or any justification – Marie Apr 23 '19 at 13:28
  • @Lewis in what situation would that happen? – zfrisch Apr 23 '19 at 13:30
  • @Lewis `0010 - 0900` is negative an will sort accordingly – adiga Apr 23 '19 at 13:31
  • @adiga Would the leading zeroes not be stripped? I.e, would it not evaluate as `10` - `9`? – Lewis Apr 23 '19 at 13:31
  • 1
    @Lewis it will be `10 - 900` – adiga Apr 23 '19 at 13:32
  • @Marie What more explanation should I add here? I thought removing `:` and subtracting would be obvious here. – adiga Apr 23 '19 at 13:36
  • @Marie I'm sorry but I'm not understanding what you're upset with. Could you explain please? The replacement of the character allows for the string to be coerced into an integer when coming into contact with an arithmetic operator. As long as the format is consistent it will work the same every time. I'm not sure where you're getting that it doesn't work with every number? – zfrisch Apr 23 '19 at 16:14
  • @zfrisch The only thing I can think is if running on old browsers, where `0300` would be interpreted as octal, so `"0300" - "0010" = 184` instead of `290`, But I don't believe there are any current browsers even in none strict that will do this now. – Keith Apr 23 '19 at 16:40
  • @Keith I was actually wrong about my assumption but that is a good point. `0300` evaluates to `192`. Thankfully the implicit cast from string to number does not parse it as octal! – Marie Apr 23 '19 at 19:17
0

You cannot subtract a string, but you can compare if it's greater than.

You can sort by using <, >,<= or >=:

var data = [{ tm: "09:00", tr: "30.34", rd: "73.23" },
    { tm: "09:10", tr: "30.45", rd: "70.77" },
    { tm: "09:50", tr: "29.95", rd: "75.70" },
    { tm: "09:40", tr: "29.95", rd: "75.70" },
    { tm: "01:50", tr: "29.95", rd: "75.70" },
    { tm: "02:30", tr: "29.95", rd: "75.70" },
    { tm: "04:50", tr: "29.95", rd: "75.70" },
    { tm: "10:00", tr: "30.05", rd: "76.20" }];
var d = data.sort(function (a, b) { return a.tm > b.tm; });
console.log(d);

In response to comments about boolean comparison

A better comparison method would be using localeCompare in numeric mode to compare values:

var data = [{ tm: "09:00", tr: "30.34", rd: "73.23" },
    { tm: "09:10", tr: "30.45", rd: "70.77" },
    { tm: "09:50", tr: "29.95", rd: "75.70" },
    { tm: "09:40", tr: "29.95", rd: "75.70" },
    { tm: "01:50", tr: "29.95", rd: "75.70" },
    { tm: "02:30", tr: "29.95", rd: "75.70" },
    { tm: "04:50", tr: "29.95", rd: "75.70" },
    { tm: "10:00", tr: "30.05", rd: "76.20" }];
var d = data.sort(function (a, b) { return a.tm.localeCompare(b.tm, undefined, { numeric: true }); });
console.log(d);

In response to comments about numeric localeCompare

Numeric localeCompare will also be useful for numbers prefixed with 0:

var data = ["01", "10", "02"];
console.log({
    original: data,
    sorted: data.slice(0).sort(function (a, b) { return a.localeCompare(b, undefined, { numeric: true }); })
});
Emil S. Jørgensen
  • 6,216
  • 1
  • 15
  • 28
  • [Sorting in JavaScript: Shouldn't returning a boolean be enough for a comparison function?](https://stackoverflow.com/questions/24080785) – adiga Apr 23 '19 at 13:37
  • `numeric` would be useful for `1,2,10`, but will have zero effect on `01,02,10` – Keith Apr 23 '19 at 16:42