I have an array:
var homes = [{
"h_id": "3",
"city": "Dallas",
"state": "TX",
"zip": "75201",
"price": "162500"
}, {
"h_id": "4",
"city": "Bevery Hills",
"state": "CA",
"zip": "90210",
"price": "319250"
}, {
"h_id": "5",
"city": "New York",
"state": "NY",
"zip": "00010",
"price": "962500"
}];
And would like to sort it based on the following order
cities = ['New York', 'Dallas', 'Bevery Hills']
What's the best way to achieve it?
I have an array:
var homes = [{
"h_id": "3",
"city": "Dallas",
"state": "TX",
"zip": "75201",
"price": "162500"
}, {
"h_id": "4",
"city": "Bevery Hills",
"state": "CA",
"zip": "90210",
"price": "319250"
}, {
"h_id": "5",
"city": "New York",
"state": "NY",
"zip": "00010",
"price": "962500"
}];
And would like to sort it based on the following order
cities = ['New York', 'Dallas', 'Bevery Hills']
What's the best way to achieve it?
Share Improve this question edited Nov 2, 2015 at 7:21 Tushar 87.2k21 gold badges163 silver badges181 bronze badges asked Nov 2, 2015 at 7:15 ambarambar 2,2537 gold badges28 silver badges33 bronze badges 2 |3 Answers
Reset to default 21There is a standard method Array.prototype.sort()
available.
Notice that the sort
method does sorting in place, so internals of homes
are going to change.
homes.sort(function (a,b){
return cities.indexOf(a.city) - cities.indexOf(b.city)
});
If you need to keep the initial array unchanged, just make a shallow copy (homes.slice(0)
) of it and sort the copy:
const sortedHomes = homes.slice(0).sort(function (a,b){
return cities.indexOf(a.city) - cities.indexOf(b.city)
});
Since you can use indexOf
on cities
to look up the final index of any home object, you can do it more efficiently than Array.prototype.sort
:
var sortedHomes = new Array(cities.length);
homes.forEach(function (home) {
var sortedIndex = cities.indexOf(home.city);
sortedHomes[sortedIndex] = home;
});
(This is still O(nm) city name comparisons, time proportional to the product of the number of cities and the number of homes – an improvement over O(nm log n), but still potentially not good with a large number of cities. You can make it O(n) by flipping cities
into a hashmap.)
If multiple homes can share the same city and cities
doesn’t contain duplicate entries (seems the most likely situation if this is the case), you can group the homes by city and combine the result as specified by cities
:
var homesByCity = {};
homes.forEach(function (home) {
var cityHomes = homesByCity[home.city];
if (cityHomes) {
cityHomes.push(home);
} else {
cityHomes = homesByCity[home.city] = [home];
}
});
var sortedHomes = [];
cities.forEach(function (city) {
(homesByCity[city] || []).forEach(sortedHomes.push, sortedHomes);
});
(The approach is O(n) on the number of cities.)
I would suggest some functional programming to solve this. The snippet below should get you the result you are looking for.
var sorted = cities.map(function(city) {
return homes.filter(function(home) {
return home.city === city;
});
});
First, map over the cities
array to create a new array based on it. Second, for each city, find the corresponding item in the homes
array and add that to the correct position in the sorted
array.
Array.prototype.sort()
? Have you checked it already? – zerkms Commented Nov 2, 2015 at 7:17