Nyveria
Nyveria

Reputation: 168

Javascript/Coffeescript Sorting an array of objects on multiple keys when the values are the same

I'm trying to sort an array of object by key but that when the value of the key of object a is the same as that of object b, the next key will be checked until they finally differ.

I've tried using the following code:

rows.sort (a, b) ->
   for key, value of a
      if a[key] < b[key]
        return -1
      else if a[key] > b[key]
        return 1
      else
        continue

But this causes the array to look differently when the initial order is different. Any ideas on a way to achieve it? Thanks!

EDIT An array before:

[ { date: "2013-02-03",
    cpc: 1.46,
    cost: 1.46,
    clicks: 1 },
  { date: "2013-02-05",
    cpc: 1.8375,
    cost: 14.7,
    clicks: 8 },
  { date: "2013-02-06",
    cpc: 1.17,
    cost: 7.02,
    clicks: 6 },
  { date: "2013-02-09",
    cpc: 0.23,
    cost: 0.23,
    clicks: 1 },
  { date: "2013-02-15",
    cpc: 1.4949999999999999,
    cost: 2.9899999999999998,
    clicks: 2 },
  { date: "2013-02-17",
    cpc: 1.21,
    cost: 2.42,
    clicks: 2 },
  { date: "2013-02-18",
    cpc: 1.92,
    cost: 9.6,
    clicks: 5 },
  { date: "2013-02-02",
    cpc: 1.86,
    cost: 1.86,
    clicks: 1 },
  { date: "2013-02-04",
    cpc: 2.35,
    cost: 2.35,
    clicks: 1 },
  { date: "2013-02-11",
    cpc: 1.9625,
    cost: 7.85,
    clicks: 4 },
  { date: "2013-02-16",
    cpc: 2.315,
    cost: 4.63,
    clicks: 2 },
  { date: "2013-02-21",
    cpc: 1.8566666666666667,
    cost: 5.57,
    clicks: 3 },
  { date: "2013-02-22",
    cpc: 1.8375,
    cost: 7.35,
    clicks: 4 },
  { date: "2013-02-25",
    cpc: 1.5066666666666668,
    cost: 4.5200000000000005,
    clicks: 3 },
  { date: "2013-02-26",
    cpc: 2.6,
    cost: 2.6,
    clicks: 1 },
  { date: "2013-02-27",
    cpc: 2.118,
    cost: 10.59,
    clicks: 5 },
  { date: "2013-02-07",
    cpc: 0.2,
    cost: 0.2,
    clicks: 1 },
  { date: "2013-02-08",
    cpc: 1.7850000000000001,
    cost: 7.140000000000001,
    clicks: 4 },
  { date: "2013-02-10",
    cpc: 0.46,
    cost: 0.46,
    clicks: 1 },
  { date: "2013-02-14",
    cpc: 1.955,
    cost: 3.91,
    clicks: 2 },
  { date: "2013-02-19",
    cpc: 1.9233333333333331,
    cost: 17.31,
    clicks: 9 },
  { date: "2013-02-12",
    cpc: 2.39,
    cost: 7.17,
    clicks: 3 },
  { date: "2013-02-13",
    cpc: 2.53,
    cost: 2.53,
    clicks: 1 },
  { date: "2013-02-20",
    cpc: 1.87,
    cost: 1.87,
    clicks: 1 },
  { date: "2013-02-23",
    cpc: 2.265,
    cost: 9.06,
    clicks: 4 },
  { date: "2013-02-28",
    cpc: 2.2425,
    cost: 8.97,
    clicks: 4 },
  { date: "2013-03-01",
    cpc: 1.83,
    cost: 3.66,
    clicks: 2 } ]

And the result after sorting (this is what I would be expecting from it):

[ { date: '2013-02-02',
    cpc: 1.86,
    cost: 1.86,
    clicks: 1 },
  { date: '2013-02-03',
    cpc: 1.46,
    cost: 1.46,
    clicks: 1 },
  { date: '2013-02-04',
    cpc: 2.35,
    cost: 2.35,
    clicks: 1 },
  { date: '2013-02-05',
    cpc: 1.8375,
    cost: 14.7,
    clicks: 8 },
  { date: '2013-02-06',
    cpc: 1.17,
    cost: 7.02,
    clicks: 6 },
  { date: '2013-02-07',
    cpc: 0.2,
    cost: 0.2,
    clicks: 1 },
  { date: '2013-02-08',
    cpc: 1.7850000000000001,
    cost: 7.140000000000001,
    clicks: 4 },
  { date: '2013-02-09',
    cpc: 0.23,
    cost: 0.23,
    clicks: 1 },
  { date: '2013-02-10',
    cpc: 0.46,
    cost: 0.46,
    clicks: 1 },
  { date: '2013-02-11',
    cpc: 1.9625,
    cost: 7.85,
    clicks: 4 },
  { date: '2013-02-12',
    cpc: 2.39,
    cost: 7.17,
    clicks: 3 },
  { date: '2013-02-13',
    cpc: 2.53,
    cost: 2.53,
    clicks: 1 },
  { date: '2013-02-14',
    cpc: 1.955,
    cost: 3.91,
    clicks: 2 },
  { date: '2013-02-15',
    cpc: 1.4949999999999999,
    cost: 2.9899999999999998,
    clicks: 2 },
  { date: '2013-02-16',
    cpc: 2.315,
    cost: 4.63,
    clicks: 2 },
  { date: '2013-02-17',
    cpc: 1.21,
    cost: 2.42,
    clicks: 2 },
  { date: '2013-02-18',
    cpc: 1.92,
    cost: 9.6,
    clicks: 5 },
  { date: '2013-02-19',
    cpc: 1.9233333333333331,
    cost: 17.31,
    clicks: 9 },
  { date: '2013-02-20',
    cpc: 1.87,
    cost: 1.87,
    clicks: 1 },
  { date: '2013-02-21',
    cpc: 1.8566666666666667,
    cost: 5.57,
    clicks: 3 },
  { date: '2013-02-22',
    cpc: 1.8375,
    cost: 7.35,
    clicks: 4 },
  { date: '2013-02-23',
    cpc: 2.265,
    cost: 9.06,
    clicks: 4 },
  { date: '2013-02-25',
    cpc: 1.5066666666666668,
    cost: 4.5200000000000005,
    clicks: 3 },
  { date: '2013-02-26',
    cpc: 2.6,
    cost: 2.6,
    clicks: 1 },
  { date: '2013-02-27',
    cpc: 2.118,
    cost: 10.59,
    clicks: 5 },
  { date: '2013-02-28',
    cpc: 2.2425,
    cost: 8.97,
    clicks: 4 },
  { date: '2013-03-01',
    cpc: 1.83,
    cost: 3.66,
    clicks: 2 } ]

When you the order is hussled, initial array:

[ { date: '2013-02-02',
    cpc: 1.86,
    cost: 1.86,
    clicks: 1 },
  { date: '2013-02-04',
    cpc: 2.35,
    cost: 2.35,
    clicks: 1 },
  { date: '2013-02-05',
    cpc: 1.8375,
    cost: 14.7,
    clicks: 8 },
  { date: '2013-02-06',
    cpc: 1.17,
    cost: 7.02,
    clicks: 6 },
  { date: '2013-02-11',
    cpc: 1.9625,
    cost: 7.85,
    clicks: 4 },
  { date: '2013-02-12',
    cpc: 2.39,
    cost: 7.17,
    clicks: 3 },
  { date: '2013-02-16',
    cpc: 2.315,
    cost: 4.63,
    clicks: 2 },
  { date: '2013-02-18',
    cpc: 1.92,
    cost: 9.6,
    clicks: 5 },
  { date: '2013-02-20',
    cpc: 1.87,
    cost: 1.87,
    clicks: 1 },
  { date: '2013-02-21',
    cpc: 1.8566666666666667,
    cost: 5.57,
    clicks: 3 },
  { date: '2013-02-28',
    cpc: 2.2425,
    cost: 8.97,
    clicks: 4 },
  { date: '2013-03-01',
    cpc: 1.83,
    cost: 3.66,
    clicks: 2 },
  { date: '2013-02-03',
    cpc: 1.46,
    cost: 1.46,
    clicks: 1 },
  { date: '2013-02-07',
    cpc: 0.2,
    cost: 0.2,
    clicks: 1 },
  { date: '2013-02-09',
    cpc: 0.23,
    cost: 0.23,
    clicks: 1 },
  { date: '2013-02-10',
    cpc: 0.46,
    cost: 0.46,
    clicks: 1 },
  { date: '2013-02-17',
    cpc: 1.21,
    cost: 2.42,
    clicks: 2 },
  { date: '2013-02-19',
    cpc: 1.9233333333333331,
    cost: 17.31,
    clicks: 9 },
  { date: '2013-02-25',
    cpc: 1.5066666666666668,
    cost: 4.5200000000000005,
    clicks: 3 },
  { date: '2013-02-08',
    cpc: 1.7850000000000001,
    cost: 7.140000000000001,
    clicks: 4 },
  { date: '2013-02-13',
    cpc: 2.53,
    cost: 2.53,
    clicks: 1 },
  { date: '2013-02-14',
    cpc: 1.955,
    cost: 3.91,
    clicks: 2 },
  { date: '2013-02-15',
    cpc: 1.4949999999999999,
    cost: 2.9899999999999998,
    clicks: 2 },
  { date: '2013-02-22',
    cpc: 1.8375,
    cost: 7.35,
    clicks: 4 },
  { date: '2013-02-23',
    cpc: 2.265,
    cost: 9.06,
    clicks: 4 },
  { date: '2013-02-26',
    cpc: 2.6,
    cost: 2.6,
    clicks: 1 },
  { date: '2013-02-27',
    cpc: 2.118,
    cost: 10.59,
    clicks: 5 }]

Result from sorting with hussled array:

[ { date: '2013-02-02',
    cpc: 1.86,
    cost: 1.86,
    clicks: 1 },
  { date: '2013-02-03',
    cpc: 1.46,
    cost: 1.46,
    clicks: 1 },
  { date: '2013-02-04',
    cpc: 2.35,
    cost: 2.35,
    clicks: 1 },
  { date: '2013-02-05',
    cpc: 1.8375,
    cost: 14.7,
    clicks: 8 },
  { date: '2013-02-06',
    cpc: 1.17,
    cost: 7.02,
    clicks: 6 },
  { date: '2013-02-07',
    cpc: 0.2,
    cost: 0.2,
    clicks: 1 },
  { date: '2013-02-08',
    cpc: 1.7850000000000001,
    cost: 7.140000000000001,
    clicks: 4 },
  { date: '2013-02-10',
    cpc: 0.46,
    cost: 0.46,
    clicks: 1 },
  { date: '2013-02-11',
    cpc: 1.9625,
    cost: 7.85,
    clicks: 4 },
  { date: '2013-02-12',
    cpc: 2.39,
    cost: 7.17,
    clicks: 3 },
  { date: '2013-02-13',
    cpc: 2.53,
    cost: 2.53,
    clicks: 1 },
  { date: '2013-02-14',
    cpc: 1.955,
    cost: 3.91,
    clicks: 2 },
  { date: '2013-02-15',
    cpc: 1.4949999999999999,
    cost: 2.9899999999999998,
    clicks: 2 },
  { date: '2013-02-16',
    cpc: 2.315,
    cost: 4.63,
    clicks: 2 },
  { date: '2013-02-17',
    cpc: 1.21,
    cost: 2.42,
    clicks: 2 },
  { date: '2013-02-18',
    cpc: 1.92,
    cost: 9.6,
    clicks: 5 },
  { date: '2013-02-19',
    cpc: 1.9233333333333331,
    cost: 17.31,
    clicks: 9 },
  { date: '2013-02-20',
    cpc: 1.87,
    cost: 1.87,
    clicks: 1 },
  { date: '2013-02-21',
    cpc: 1.8566666666666667,
    cost: 5.57,
    clicks: 3 },
  { date: '2013-02-22',
    cpc: 1.8375,
    cost: 7.35,
    clicks: 4 },
  { date: '2013-02-23',
    cpc: 2.265,
    cost: 9.06,
    clicks: 4 },
  { date: '2013-02-09',
    cpc: 0.23,
    cost: 0.23,
    clicks: 1 },
  { date: '2013-02-25',
    cpc: 1.5066666666666668,
    cost: 4.5200000000000005,
    clicks: 3 },
  { date: '2013-02-26',
    cpc: 2.6,
    cost: 2.6,
    clicks: 1 },
  { date: '2013-02-27',
    cpc: 2.118,
    cost: 10.59,
    clicks: 5 },
  { date: '2013-02-28',
    cpc: 2.2425,
    cost: 8.97,
    clicks: 4 },
  { date: '2013-03-01',
    cpc: 1.83,
    cost: 3.66,
    clicks: 2 } ]

Upvotes: 0

Views: 322

Answers (2)

I was about asking this question but found there was a similar question, turned out that the answer was something I was already doing but this had a FOR IN loop. I tested it out and it wasn't giving me what I wanted Then I decided to swap out the for in loop for a little more code when the values are the same. Here are the results

Looping through the given keys and comparing all

The loop outcome

Comparing a different key  value pair when the initial values compared are the same

The outcome

Upvotes: 0

Paul Roub
Paul Roub

Reputation: 36458

You don't need the continue. And make sure to return 0 when the objects are a match:

rows.sort (a, b) ->
  for key, value of a
    if a[key] < b[key]
      return -1
    else if a[key] > b[key]
      return 1

  return 0

The larger problem - object keys aren't sorted. There's no reason to expect, each time through the for loop, that the first key will be date, the second will be cpc, etc. You really want to have a predefined array of the keys, in order, and use that instead of just getting the key list from the objects

keys = ["a","b","c"]

rows.sort (a, b) ->
  for key in keys
    if a[key] < b[key]
      return -1
    else if a[key] > b[key]
     return 1

  return 0

Example

Upvotes: 3

Related Questions