0

I have an array with a list of locations.

I am adding on 3 properties detailing where each location is in relation to a set start location.

Each location in the array has the following 3 properties:

bearing (0 to 360 degrees)
humanFriendlyCompassHeading (North, North East, East etc)
distance (in km)

I am able to sort the array by bearing so the locations are listed from 0 to 360 degrees and the human friendly compass headings are in order so the first few entries in the array are North, followed by NorthEast, East etc.

However, I would like the distances to be then sorted from nearest to furthest away for each human friendly compass heading i.e. North, NorthEast, East.

This is what I have so far using the code provided below and the comparison function:

var myCmp = composeComparisons([sortArrayByBearing, sortArrayByHumanFriendlyCompassHeading, sortArrayByDistance]);
res.geonames.sort(myCmp);


function sortArrayByDistance(A, B)
{
return parseFloat(A.distance) - parseFloat(B.distance);
}

function sortArrayByBearing(A, B)
{
return parseFloat(A.bearing) - parseFloat(B.bearing);
}

//Used to sort results array by humanFriendlyCompassHeading
//usage: results.sort(sortArrayByHumanFriendlyCompassHeading);
//The sorting of humanFriendlyCompassHeading is realised with a map and look up for the value.
function sortArrayByHumanFriendlyCompassHeading(A, B) {
var DIRECTIONS = { North: 0, NorthEast: 1, East: 2, SouthEast: 3, South: 4, SouthWest: 5, West: 6, NorthWest: 7};
return         DIRECTIONS[A.humanFriendlyCompassHeading] - DIRECTIONS[B.humanFriendlyCompassHeading];
}

Here is a sample output of how I would like the data to be sorted:

  • (514m, North) Nottingham Trent University, School of Art and Design

  • (695m, North) The Arboretum, Nottingham

  • (424m, NorthEast) Archiam Centre

  • (497m, NorthEast) Shakespeare Street Wesleyan Reform Chapel

  • (795m, NorthEast) Nottingham Urban Area

  • (796m, NorthEast) Victoria bus station, Nottingham

  • (438m, East) Nottingham Conference Centre

This is part of the original array. I am adding on the bearing, distance and human friendly values from my start location later on using the lat and lng values returned in the array:

         "summary":"The Diocese of Nottingham, England, is a Roman Catholic diocese of the Latin Rite which covers an area of 13,074 km², taking in the counties of Nottinghamshire (excluding the district of Bassetlaw), Leicestershire, Derbyshire, Rutland and Lincolnshire (...)",
     "elevation":65,
     "lng":-1.1572,
     "distance":"0.0685",
     "countryCode":"GB",
     "rank":84,
     "lang":"en",
     "title":"Roman Catholic Diocese of Nottingham",
     "lat":52.9545,
     "wikipediaUrl":"en.wikipedia.org/wiki/Roman_Catholic_Diocese_of_Nottingham"
  },
  {  
     "summary":"The Cathedral Church of St. Barnabas in the city of Nottingham, England, is a cathedral of the Roman Catholic church. It is the mother church of the Diocese of Nottingham and seat of the Bishop of Nottingham. (...)",
     "elevation":67,
     "feature":"landmark",
     "lng":-1.15708,
     "distance":"0.0703",
     "countryCode":"GB",
     "rank":82,
     "lang":"en",
     "title":"Nottingham Cathedral",
     "lat":52.95466,
     "wikipediaUrl":"en.wikipedia.org/wiki/Nottingham_Cathedral"
  },
  {  
     "summary":"The Albert Hall, Nottingham, is a City Centre Conference and Concert venue, situated in Nottingham, England. (...)",
     "elevation":61,
     "feature":"landmark",
     "lng":-1.1563944444444442,
     "distance":"0.1217",
     "countryCode":"GB",
     "rank":72,
     "lang":"en",
     "title":"Albert Hall, Nottingham",
     "lat":52.95441944444445,
     "wikipediaUrl":"en.wikipedia.org/wiki/Albert_Hall%2C_Nottingham"
  },
  {  
     "summary":"The Nottingham Playhouse is a theatre in Nottingham, Nottinghamshire, England. It was first established as a repertory theatre in the 1950s when it operated from a former cinema. Directors during this period included Val May and Frank Dunlop (...)",
     "elevation":67,
     "feature":"landmark",
     "lng":-1.1577,
     "distance":"0.1235",
     "countryCode":"GB",
     "rank":77,
     "lang":"en",
     "title":"Nottingham Playhouse",
     "lat":52.9537,
     "wikipediaUrl":"         en.wikipedia.org/wiki/Nottingham_Playhouseenter code here
6
  • 1
    can you add some example of the data, please? Commented Jan 1, 2016 at 21:51
  • thank you for the output data, but we need the raw data before the sorting. Commented Jan 2, 2016 at 8:27
  • I've updated my original question. I've tried your code but I still can't get it to sort correctly. I'm fetching the location results from the geonames web API and then calculating and adding on the bearing, distance and human friendly compass headings using the lat and lng values for each of the locations returned. bearings are in the range 0 to 360 HumanFriendlyCompassHeadings are either North, NorthEast, East, SouthEast, South, SouthWest, West or NorthWest distances are in km for example 0.2999874 Commented Jan 2, 2016 at 10:36
  • please post a part of the original array. Commented Jan 2, 2016 at 12:01
  • Could you pass your original JSON to something like that before putting it here please: jsonprettyprint.com Commented Jan 4, 2016 at 8:34

2 Answers 2

1

To compose comparison functions for use with Array.prototype.sort, you can use a function such as this one:

function composeComparisons(cmpFunctions) {
     return function (a, b) {
          for (var i = 0, result; i < cmpFunctions.length; i++) {
                result = cmpFunctions[i](a, b);
                if (result) {
                    return result;
                }
          }
          return 0;
     }
};

It will return a function that compares items with each of your comparison function until a significant result is obtained.

You'd use it like that:

// From most significant to least significant comparison function
var myCmp = composeComparisons([cmpByBearing, cmpByDistance, cmpByFriendliness]);

array.sort(myCmp);

As a reminder, a comparison function cmp(a, b) returns a positive number if a is greater than b, a negative number if b is greater than a, and 0 if items are the same.

Sign up to request clarification or add additional context in comments.

Comments

1

Your supposed sorting order

  • bearing (0 to 360 degrees) [no data here]
  • humanFriendlyCompassHeading
  • distance (in metres)

can be realised with sorting with the following function.

The function takes for every sorting group the difference and if it is the same (this is the value 0), then the next group is taken and sorted by the result of the difference, and so on.

The sorting of humanFriendlyCompassHeading, (here reworded with compassDirection) is realised with a map and look up for the value.

var data = [
    { distance: 695, compassDirection: 'North', target: 'The Arboretum, Nottingham' },
    { distance: 497, compassDirection: 'NorthEast', target: 'Shakespeare Street Wesleyan Reform Chapel' },
    { distance: 438, compassDirection: 'East', target: 'Nottingham Conference Centre' },
    { distance: 514, compassDirection: 'North', target: 'Nottingham Trent University, School of Art and Design' },
    { distance: 795, compassDirection: 'NorthEast', target: 'Nottingham Urban Area' },
    { distance: 424, compassDirection: 'NorthEast', target: 'Archiam Centre' },
    { distance: 796, compassDirection: 'NorthEast', target: 'Victoria bus station, Nottingham' }
];

data.sort(function (a, b) {
    var D = { North: 0, NorthEast: 45, East: 90, /* ... */ };
    return D[a.compassDirection] - D[b.compassDirection] || a.distance - b.distance;
});

document.write('<pre>' + JSON.stringify(data, 0, 4) + '</pre>');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.