I have the following array structure
[{
name: "Mobile Uploads"
}, {
name: "Profile Pictures"
}, {
name: "Reports"
}, {
name: "Instagram Photos"
}, {
name: "Facebook"
}, {
name: "My Account"
}, {
name: "Twitter"
}]
I want to reorder the array so that its in the following order: Profile Pictures
, Mobile Uploads
, Instagram Photos
, and the objects afterwards are in alpabetical order.
I have the following array structure
[{
name: "Mobile Uploads"
}, {
name: "Profile Pictures"
}, {
name: "Reports"
}, {
name: "Instagram Photos"
}, {
name: "Facebook"
}, {
name: "My Account"
}, {
name: "Twitter"
}]
I want to reorder the array so that its in the following order: Profile Pictures
, Mobile Uploads
, Instagram Photos
, and the objects afterwards are in alpabetical order.
-
2
Rather than thinking of moving elements around, think of creating a new array with the elements in the order you want. You can use routines like
sort
, ormap
, orfilter
to do that. That's how we usually do it in JS. By the way, you've used the word "efficiently" here. I see that quite a bit in JS questions. Technically speaking, that means "fast performance". Is that what you mean, or do you really mean, as is often the case, "in a way that's easy to read and write"? – user663031 Commented Jul 19, 2016 at 3:12 - Hey @Brown, so you are looking for 2 orders: Profile Pictures, Mobile Uploads, Instagram Photos and Instagram Photos, Mobile Uploads, Profile Pictures – Ayan Commented Jul 19, 2016 at 3:15
- 2 stackoverflow./questions/2440700/reordering-arrays – Venkat Commented Jul 19, 2016 at 4:02
3 Answers
Reset to default 10What you want to do is to make an object that holds the sort exceptions. Then you can write a custom sort()
function that accounts for your exceptions.
var list = [{
name: "Date"
}, {
name: "Mobile Uploads"
}, {
name: "Profile Pictures"
}, {
name: "Fig"
}, {
name: "Instagram Photos"
}, {
name: "Cherry"
}, {
name: "Apple"
}, {
name: "Banana"
}];
var exceptions = {
"Profile Pictures": 1,
"Mobile Uploads": 2,
"Instagram Photos": 3
}
list.sort(function(a, b) {
if (exceptions[a.name] && exceptions[b.name]) {
//if both items are exceptions
return exceptions[a.name] - exceptions[b.name];
} else if (exceptions[a.name]) {
//only `a` is in exceptions, sort it to front
return -1;
} else if (exceptions[b.name]) {
//only `b` is in exceptions, sort it to back
return 1;
} else {
//no exceptions to account for, return alphabetic sort
return a.name.localeCompare(b.name);
}
});
console.log(list);
var algo = [{
name: "Mobile Uploads"
},
{
name: "Zeta"
},
{
name: "Beta"
},
{
name: "Alfa"
},
{
name: "Profile Pictures"
},
{
name: "Instagram Photos"
}]
var pare = function(a,b){
var weight = {"Profile Pictures":1, "Mobile Uploads":2, "Instagram Photos":3}
, nameA = a.name
, weightA = weight[nameA] || 100
, nameB = b.name
, weightB = weight[nameB] || 100
if(weightA != weightB){
return weightA - weightB;
}else{
return nameA > nameB;
}
}
console.log(algo.sort(pare));
the idea is assign weight to manage the sort.
I believe the best way to do this is just do everything with a custom sort
. The sort callback function is given two arguments, the first array element and the second array element which it is paring. Then you can use any logic you wish within the body of the callback to decide what to return. If -1 is returned, then this means the first element should be before the second element. If 1 is returned, then this means the second element should be before the first element. If 0 is returned, this means both elements are equal and thus should remain side-by-side with each other so no other elements get inserted into the middle during sorting.
To sort alphabetically, you can pare two strings with each other using the <
, >
, <=
, >=
operators. Then the result would be a boolean true or false, so you'd want to return either -1
or 1
depending whether you wanted ascending or descending - in respect to the way you pared them. You can also check for equality and return 0
if you think you'll be encountering duplicate items in your array and wanted to have a slightly faster implementation which will be barely noticeable unless you were working on large data.
To add exceptions to the alphabetical sorting, I'd suggest creating a numeric representation for the first element, then create another numeric representation for the second element. Use negative numbers to indicate sorting among exceptions, where the smaller the number would indicate the closer to the beginning of the array it should go. Then use a 0 for everything else to indicate it isn't an exception. Then finally check for the existence of exceptions using a simple if statement. In the case of no exceptions, sort alphabetical. Otherwise we have an exception and should sort in the order of whichever is represented by the smaller number.
var inputArray = [{
name: "Mobile Uploads"
}, {
name: "Profile Pictures"
}, {
name: "Reports"
}, {
name: "Instagram Photos"
}, {
name: "Facebook"
}, {
name: "My Account"
}, {
name: "Twitter"
}];
var sortedArray = inputArray.slice(0);//copy of the original array as sort is destructive.
sortedArray.sort(function(a,b){
var aIndex = 0, bIndex = 0;
switch(a.name)
{
case "Profile Pictures":
aIndex = -3;
break;
case "Mobile Uploads":
aIndex = -2;
break;
case "Instagram Photos":
aIndex = -1;
break;
}
switch(b.name)
{
case "Profile Pictures":
bIndex = -3;
break;
case "Mobile Uploads":
bIndex = -2;
break;
case "Instagram Photos":
bIndex = -1;
break;
}
if(aIndex < 0 || bIndex < 0)//Check if either element being pared needs special treatment
{
//in the case of two exceptions, we want the smallest one to be sorted first
//otherwise in the case of one exception the other element would be a 0
return aIndex < bIndex ? -1 : 1;//ascending
}
else
{
//otherwise just sort in alpabetical order paring strings with the less than operator
return a.name < b.name ? -1 : 1;//ascending
}
});
//Before
console.log('Before:');
console.log(inputArray.map(function(v){
return v.name;
}).join(', '));//Mobile Uploads, Profile Pictures, Reports, Instagram Photos, Facebook, My Account, Twitter
//After
console.log('After:');
console.log(sortedArray.map(function(v){
return v.name;
}).join(', '));//Profile Pictures, Mobile Uploads, Instagram Photos, Facebook, My Account, Reports, Twitter