Reputation: 39
How do I sort banana after apple always?
arr = [
{ 'id' : 1, 'fruit' : 'apple' },
{ 'id' : 2, 'fruit' : 'banana' },
{ 'id' : 3, 'fruit' : 'custard' },
{ 'id' : 4, 'fruit' : 'banana' },
{ 'id' : 5, 'fruit' : 'apple' },
{ 'id' : 6, 'fruit' : 'custard' }
];
expected:
arr = [
{ 'id' : 1, 'fruit' : 'apple' },
{ 'id' : 3, 'fruit' : 'custard' },
{ 'id' : 5, 'fruit' : 'apple' },
{ 'id' : 2, 'fruit' : 'banana' },
{ 'id' : 4, 'fruit' : 'banana' },
{ 'id' : 6, 'fruit' : 'custard' }
];
So banana should always appear after apple, or apple should be sorted before banana.
this is what i've tried:
arr.sort(function(a, b) {
return (a.fruit === 'banana') - (b.fruit === 'banana')
})
but in this case, banana always gets sorted at the end of the array, which is not what i'm going for. all the 'banana' items should be automatically sorted after the last 'apple' item
Upvotes: 0
Views: 523
Reputation: 350137
You can simply sort by item2
(alphabetically).
arr.sort((a, b) => a.item2.localeCompare(b.item2));
This will put all records in alphabetical order based on item2
.
If however you want to perform the minimum number of swaps, then I suggest you don't use sort
, but loop the array by bringing two indices towards each other starting at both ends:
let arr = [
{ 'item1' : 1, 'item2' : 'apple' },
{ 'item1' : 2, 'item2' : 'banana' },
{ 'item1' : 3, 'item2' : 'custard' },
{ 'item1' : 4, 'item2' : 'banana' },
{ 'item1' : 5, 'item2' : 'apple' },
{ 'item1' : 6, 'item2' : 'custard' }
];
let i = 0;
let j = arr.length-1;
while (true) {
while (i < j && arr[i].item2 !== "banana") {
i++;
}
while (i < j && arr[j].item2 !== "apple") {
j--;
}
if (i >= j) {
break;
}
[arr[i], arr[j]] = [arr[j], arr[i]]; // swap
i++;
j--;
}
console.log(arr);
Upvotes: 1
Reputation: 28196
This will in a first step separate the array into two: res[true]
containing all the "banana"-elements and res[false]
all the others. In a second step the array res[true]
is .splice()
-ed into the res[false]
array after the last index of "apple".
const arr = [
{ 'item1' : 1, 'item2' : 'apple' },
{ 'item1' : 2, 'item2' : 'banana' },
{ 'item1' : 3, 'item2' : 'custard' },
{ 'item1' : 4, 'item2' : 'banana' },
{ 'item1' : 5, 'item2' : 'apple' },
{ 'item1' : 6, 'item2' : 'custard' }
];
let res=arr.reduce(
(a,c)=>(a[c.item2==="banana"].push(c),a),
{true:[],false:[]} );
let pos=res[false].map(e=>e.item2).lastIndexOf("apple")+1;
// in case "apple" was not found: simply copy arr:
res=pos?(res[false].splice(pos,0,...res[true]),res[false]):arr.slice(0);
console.log(res);
res
contains the final result.
Upvotes: 0