I have a map that’s declared like var cars = new Map<string, object>();
, where the string
is the model of the car and the object
has information like year
and price
.
Therefore, the Map
will look like this:
Map = [
'BMW' => {
id: 123,
price: 2000,
models: {...}
},
'Opel' => {
id: 1234,
price: 3500,
models: {...}
},
....
]
I would like to sort all the entires by the price
field (asc, or desc).
I couldn’t figure out any solution, since iterating over the values
would lose the keys, and solutions like I read around with ...cars.entries()
doesn’t apply since the values are not iterable.
P.S. I am currently using TypeScript, but the solution for JS should apply nonetheless.
Edit: I tried converting the map to an array, like this:
const values = Array.from(this.cars.values());
values.sort((a, b) => {
return (a.price < b.price) ? -1 : 1;
});
But I had some troubles reconstructing the Map to keep the keys
…
I have a map that’s declared like var cars = new Map<string, object>();
, where the string
is the model of the car and the object
has information like year
and price
.
Therefore, the Map
will look like this:
Map = [
'BMW' => {
id: 123,
price: 2000,
models: {...}
},
'Opel' => {
id: 1234,
price: 3500,
models: {...}
},
....
]
I would like to sort all the entires by the price
field (asc, or desc).
I couldn’t figure out any solution, since iterating over the values
would lose the keys, and solutions like I read around with ...cars.entries()
doesn’t apply since the values are not iterable.
P.S. I am currently using TypeScript, but the solution for JS should apply nonetheless.
Edit: I tried converting the map to an array, like this:
const values = Array.from(this.cars.values());
values.sort((a, b) => {
return (a.price < b.price) ? -1 : 1;
});
But I had some troubles reconstructing the Map to keep the keys
…
- Possible duplicate of Sort array of objects by string property value in JavaScript – Nope Commented Feb 15, 2018 at 16:49
- 1 @Nope not really, since that's just sorting of objects. My problem is when re-constructing the Map to keep the original keys for each value – LostCoder Commented Feb 15, 2018 at 16:57
3 Answers
Reset to default 4A Map
object iterates and keeps its elements in insertion order. So only solution for you to create new Map
. Easiest way i think is to convert old map to array, sort it, and convert to a new map. Like this :
let newMap = new Map([...map].sort(([k, v], [k2, v2])=> {
if (v.price > v2.price) {
return 1;
}
if (v.price < v2.price) {
return -1;
}
return 0;
}));
Maps are sorted after insertion time. Thats how it is. If you want to sort it differently you could build up an array that points to the same objects the map does, but has a different order. To then get the Map key, it would make sense to store it in the object directly. To set up the array, one might use insertion sort:
const sorted: object[] = [];
for(const [key, car] of cars){
car.name = key;
const insertAt = sorted.findIndex(other => other.price < car.price) + 1;
sorted.splice(insertAt, 0, car);
}
Alternatively you could sort afterwards (shorter + slower):
const sorted = [...cars.entries()].map(([name, car]) => ({name, ...car})).sort((a, b) => a.price - b.price);
Note that using typescript makes no sense if you just fall back to native types. You might implement a car interface instead, e.g.:
interface ICar {
price: number;
models: IModel[];
id: number;
name: string;
}
Using the ideas from Anton and Jonas, I got to this solution. It's not perfect tho, but seems to work
private sortCars(cars): Map<string, iCar> {
// Convert the map to array first and sort it by "price"
const carList = Array.from(cars)
.map(([brand, car]) => ({brand, ...car}))
.sort((a, b) => {
if (a.price === b.price) {
return 0;
} else {
return a.price < b.price ? -1 : 1;
}
}
);
// Rebuild the map after sorting it.
const carsMap = new Map();
carList.forEach((car) => carsMap.set(car.name, car));
return carsMap;
}
I chose to rather add the brand name to the car object as well, in order to re-build the final Map. I could have, instead, search for the object in the original map and return the key.