Given array:
var someAnswers = [
{
answer: 'Lyndon Johnson', // answer A
comment: '...'
},
{
answer: 'Richard Nixon', // answer B
comment: '...'
},
{
answer: 'Jimmy Carter', // answer C
comment: '...'
},
{
answer: 'Gerald Ford', // answer D
comment: '...'
}
];
Some custom order:
customOrder = 'A, C, B, D';
or
customOrder = ['A', 'C', 'B', 'D'];
Do something like this:
someAnswers.sort(customOrder);
Desired result:
[
{
"answer": "Lyndon Johnson",
"comment": "..."
},
{
"answer": "Jimmy Carter",
"comment": "..."
},
{
"answer": "Richard Nixon",
"comment": "..."
},
{
"answer": "Gerald Ford",
"comment": "..."
}
]
Another custom order:
anotherCustomOrder = 'D, B, A, C';
or
anotherCustomOrder = ['D', 'B', 'A', 'C'];
Do something like this:
someAnswers.sort(anotherCustomOrder);
Desired result:
[
{
"answer": "Gerald Ford",
"comment": "..."
},
{
"answer": "Richard Nixon",
"comment": "..."
},
{
"answer": "Lyndon Johnson",
"comment": "..."
},
{
"answer": "Jimmy Carter",
"comment": "..."
}
]
CodePudding user response:
let sorting = (currentArray, indexArr) => {
const reArrangedArr = [];
const deepCopied = JSON.parse(JSON.stringify(currentArray));
indexArr.forEach(index => reArrangedArr.push(deepCopied[index]));
return reArrangedArr;
}
var someAnswers = [
{
answer: 'Lyndon Johnson', // answer A
comment: '...'
},
{
answer: 'Richard Nixon', // answer B
comment: '...'
},
{
answer: 'Jimmy Carter', // answer C
comment: '...'
},
{
answer: 'Gerald Ford', // answer D
comment: '...'
}
];
sorting(someAnswers, [3,0,1,2])
let sorting = (currentArray, indexArr) => {
const reArrangedArr = [];
const deepCopied = JSON.parse(JSON.stringify(currentArray));
indexArr.forEach(index => reArrangedArr.push(deepCopied[index]));
return reArrangedArr;
}
var someAnswers = [
{
answer: 'Lyndon Johnson', // answer A
comment: '...'
},
{
answer: 'Richard Nixon', // answer B
comment: '...'
},
{
answer: 'Jimmy Carter', // answer C
comment: '...'
},
{
answer: 'Gerald Ford', // answer D
comment: '...'
}
];
console.log(sorting(someAnswers, [3,0,1,2]))
CodePudding user response:
If you were willing to replace the letters with numbers in customOrder, you could do something like this:
customOrder = [0, 2, 1, 3];
sort(someAnswers, customOrder) {
res = [];
customOrder.forEach((n) => {
res.push(someAnswers[n]);
}
return res;
}
Alternatively, if you really want to use letters:
customOrder = ["A", "C", "B", "D"];
sort(someAnswers, customOrder) {
res = [];
customOrder.forEach((n) => {
res.push(someAnswers[n.charCodeAt(0) - 65]);
}
return res;
}
CodePudding user response:
You can create an object with the indexes according to the desired order, and then use the function Array.prototype.map
and extract the values by using the previously created indexes array.
const someAnswers = [ { answer: 'Lyndon Johnson', comment: '...' }, { answer: 'Richard Nixon', comment: '...' }, { answer: 'Jimmy Carter', comment: '...' }, { answer: 'Gerald Ford', comment: '...' }],
answerIndexes = ['A', 'B', 'C', 'D'].reduce((a, c, i) => ({...a, [c]: i}), {}),
customOrder = ['A', 'C', 'B', 'D'],
sorted = customOrder.map(L => someAnswers[answerIndexes[L]]);
console.log(sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
Wrap → sort → unwrap
const toLetter = num =>
String.fromCharCode(num 65);
const wrap = (item, index) =>
({ letter: toLetter(index), item });
const unwrap = ({item}) => item;
const sorter = lookup => ({letter: a}, {letter: b}) =>
lookup.indexOf(a) - lookup.indexOf(b);
function sortCustom(arr, order) {
return arr
.map(wrap)
.sort(sorter(order))
.map(unwrap);
}
var someAnswers = [ { answer: 'Lyndon Johnson', comment: '...' }, { answer: 'Richard Nixon', comment: '...' }, { answer: 'Jimmy Carter', comment: '...' }, { answer: 'Gerald Ford', comment: '...' } ];
var customOrder = ['A', 'C', 'B', 'D'];
console.log(sortCustom(someAnswers, customOrder));
This will process the data in three steps:
It wraps every item in a sortable container. For example, the first item:
{ answer: 'Lyndon Johnson', // answer A comment: '...' }
becomes:
{ letter: "A", item: { answer: 'Lyndon Johnson', comment: '...' } }
- The transformation to a letter uses the character codes. A capital "A" is
65
and each following capital letter is one more - "B" is66
etc. - The wrapping here is done to avoid having to lookup in which position each item was originally in order to find out which letter it corresponds to. The data is computed once and placed on the sortable container and the item is also kept there for easy access.
- The transformation to a letter uses the character codes. A capital "A" is
Sorts based on another array according to
letter
.Unwraps the sortable container back to the base item again once the sorting information is no longer needed.
This is a straightforward implementation of the idea. The sorter
function can be inefficient for large arrays as it will have to do a lot of lookup to find the order. One way to avoid it is to cache the lookup data, in order to avoid indexOf
traversing the array multiple times:
const sorter = order => {
const lookup = Object.fromEntries(order.map((x, i) => [x, i]))
return ({letter: a}, {letter: b}) =>
lookup[a] - lookup[b];
};
Transform order to a new array
const toIndex = letter =>
letter.charCodeAt(0) - 65;
function sortCustom(arr, order) {
return order.map(x => arr[toIndex(x)]);
}
var someAnswers = [ { answer: 'Lyndon Johnson', comment: '...' }, { answer: 'Richard Nixon', comment: '...' }, { answer: 'Jimmy Carter', comment: '...' }, { answer: 'Gerald Ford', comment: '...' } ];
var customOrder = ['A', 'C', 'B', 'D'];
console.log(sortCustom(someAnswers, customOrder));
In a way, this is the inverse of sorting. We take the already sorted order
array and directly transform it into the array of items via .map()
. The key thing here is using the opposite of toLetter()
- toIndex()
takes a letter and returns the corresponding index.