Reputation: 271
I have an array of javascript arrays, with each inner array being of equal length. I want to sort one of the inner arrays chronologically (its members are all numbers), and I want the other arrays to re-order in the same way. E.g.
we start with this:
[[2, 3, 1], ["deux", "trois", "un"], ["zwei", "drei", "eins"]]
and the result I want is:
[[1, 2, 3], ["un", "deux", "trois"], ["eins", "zwei", "drei"]]
I've tried different variations on the following, but had no luck:
arr.sort((a, b) => a[0] - b[0])
All I get back is exactly what I put in!
Upvotes: 3
Views: 1066
Reputation: 386540
You could get an array of sorted indices and map sorted arrays.
const
arrays = [[2, 3, 1], ["deux", "trois", "un"], ["zwei", "drei", "eins"]],
sorted = arrays.map(
(indices => a => indices.map(i => a[i]))
([...arrays[0].keys()].sort((a, b) => arrays[0][a] - arrays[0][b]))
);
console.log(sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A function for it.
const
sortNumbers = (a, b) => a - b,
sortABC = (a, b) => a.localeCompare(b),
sortArray = (arrays, index, fn) => {
const
source = arrays[index],
indices = [...source.keys()].sort((a, b) => fn(source[a], source[b]));
return arrays.map(a => indices.map(i => a[i]));
},
arrays = [[2, 3, 1], ["deux", "trois", "un"], ["zwei", "drei", "eins"]],
sorted0 = sortArray(arrays, 0, sortNumbers),
sorted1 = sortArray(arrays, 1, sortABC);
sorted2 = sortArray(arrays, 2, sortABC);
console.log(sorted0);
console.log(sorted1);
console.log(sorted2);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 13366
const test = [
[3, 2, 1, 3, 2, 1, 2],
["trois", "deux", "un", "trois", "deux", "un", "deux"],
["drei", "zwei", "eins", "drei", "zwei", "eins", "zwei"]
];
function sortListsAccordingToReferenceList(
listOfLists,
listIndex,
referenceComparator
) {
function defaultComparator(a, b) {
return (
((a.localeCompare) && (b.localeCompare))
? a.localeCompare(b)
: (((a < b) && -1) || ((a > b) && 1) || 0)
);
}
const comparator = (typeof referenceComparator === 'function')
? referenceComparator
: defaultComparator;
function compareReferenceItems(a, b) {
return comparator(a.value, b.value);
}
const referenceList = listOfLists[listIndex];
const lastIndexList = referenceList.map((item, idx) => ({
lastIndex: idx,
value: item
})).sort(compareReferenceItems).map(referenceItem =>
referenceItem.lastIndex
);
// console.log('lastIndexList : ', lastIndexList);
// - in case of needing to return the
// mutated original array use this block ...
//
// listOfLists.forEach((list, idx) => {
//
// const duplicates = Array.from(list);
// lastIndexList.forEach((lastIndex, idx) => {
//
// list[idx] = duplicates[lastIndex];
// });
// });
// return listOfLists; // return mutated original array.
// - ... otherwise go with pure mappping.
return listOfLists.map(list =>
list.map((item, idx) => list[lastIndexList[idx]])
);
}
console.log(
'sort every array according to numeric sort order ...',
sortListsAccordingToReferenceList(test, 0)
);
console.log(
'sort everything by French as lexicographic sort reference ...',
sortListsAccordingToReferenceList(test, 1)
);
console.log(
'sort everything by German as lexicographic sort reference ...',
sortListsAccordingToReferenceList(test, 2)
);
console.log(
'sort every array according to numeric custom sort order ...',
sortListsAccordingToReferenceList(test, 0, (a, b) =>
// comparator function for descending sort order
(((a > b) && -1) || ((a < b) && 1) || 0)
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Upvotes: 1
Reputation: 177702
Not a oneliner, but easier to read
let nested = [
[2, 3, 1],
["deux", "trois", "un"],
["zwei", "drei", "eins"]
];
let srcArr;
nested = nested.map((arr, i) => {
if (i === 0) { // the reference
srcArr = arr.slice(0); // take a copy
arr.sort((a, b) => a - b); // sort the nested one
return arr;
}
return arr.map((item, i) => arr[
srcArr.indexOf(nested[0][i]) // return in the order of the reference
]);
})
console.log(nested)
Upvotes: 0
Reputation: 1342
This should do the trick, we should get the new indexes for array of numbers then apply the same new indexes to non number arrays:
const arrays = [
[2, 3, 1],
["deux", "trois", "un"],
["zwei", "drei", "eins"],
];
const [arrNbrs] = arrays;
const newIndexes = [...arrNbrs].sort().map((nbr) => arrNbrs.indexOf(nbr));
const sortedArrays = arrays.map((subArray) =>
subArray.map((_, index) => subArray[newIndexes[index]])
);
console.log("sortedArrays", sortedArrays);
Upvotes: 2