I have an array of a dynamic sizing that changes its order based on what is last selected to position 0 of the array. Problem is I want to keep the original order of the array.
In order to do that, I have created an additional variable that is set to the original sorting of the array. Although some of the values of the array might change after the selecting of the item, the name property never does. I want to use this fact to sort the new array to the original position.
let keepRateOrder = rates.sort((a, b) => {
return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
});
const rates = [
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]
const prevRates = [
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]
This can be solved using findIndex. In the following example the sort will put Mail first as per the prevRates array:
const rates = [
{name:'UPS', isChoosen:true, cost:63},
{name:'Mail', isChoosen:false, cost:23},
{name:'FedEx', isChoosen:false, cost:33}
];
const prevRates = [
{name: 'Mail'},
{name: 'UPS'},
{name: 'FedEx'},
];
let keepRateOrder = rates.sort((a, b) => {
return prevRates.findIndex(p => p.name === a.name) - prevRates.findIndex(p => p.name === b.name);
});
console.log(keepRateOrder);
You could accomplish the same thing with indexOf if you map first. This leads to somewhat cleaner code:
const rates = [
{name:'UPS', isChoosen:true, cost:63},
{name:'Mail', isChoosen:false, cost:23},
{name:'FedEx', isChoosen:false, cost:33}
];
const prevRates = [
{name: 'Mail'},
{name: 'UPS'},
{name: 'FedEx'},
].map(x => x.name);
let keepRateOrder = rates.sort((a, b) => {
return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
});
console.log(keepRateOrder);
And here's one more solution just using a hash of the original indexes, created using reduceRight:
const rates = [
{name:'UPS', isChoosen:true, cost:63},
{name:'Mail', isChoosen:false, cost:23},
{name:'FedEx', isChoosen:false, cost:33}
]
const prevRates = [
{name: 'Mail'},
{name: 'UPS'},
{name: 'FedEx'},
].reduceRight((a, x, i) => (a[x.name] = i, a), {});
let keepRateOrder = rates.sort((a, b) => {
return prevRates[a.name] - prevRates[b.name];
});
console.log(keepRateOrder);
Since you said that items may be added or removed from the original array, note that all of the above solutions will place new items first (since their index in the prevRates array will be returned as -1). If you want new items to appear at the end, you'll need to do something like this:
const rates = [
{name:'UPS', isChoosen:true, cost:63},
{name:'Mail', isChoosen:false, cost:23},
{name:'Foo'},
{name:'FedEx', isChoosen:false, cost:33},
];
const prevRates = [
{name: 'Mail'},
{name: 'UPS'},
{name: 'FedEx'},
].map(x => x.name);
let keepRateOrder = rates.sort((a, b) => {
const aIndex = prevRates.indexOf(a.name);
const bIndex = prevRates.indexOf(b.name);
return (aIndex === -1 ? Number.MAX_VALUE : aIndex) - (bIndex === -1 ? Number.MAX_VALUE : bIndex);
});
console.log(keepRateOrder);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With