Reputation: 3227
I have an array like this:
var arr = [
{a: 1, b: ['apple', 'banana', 'orange', 'mango'], c: [42, 7, 18, 5]},
{a: 2, b: ['apple', 'banana', 'orange', 'mango'], c: [4, 101, 88, 3]},
{a: 3, b: ['apple', 'banana', 'orange', 'mango'], c: [14, 10, 5, 12]},
{a: 4, b: ['apple', 'banana', 'orange', 'mango'], c: [99, 2, 105, 101]}
];
I need to sort both arr[x].b
and arr[x].c
depending on arr[x].c
values, if that makes sense. So, the final array should look like this:
arr = [
{a: 1, b: ['mango', 'banana', 'orange', 'apple'], c: [5, 7, 18, 42]},
{a: 2, b: ['mango', 'apple', 'orange', 'banana'], c: [3, 4, 88, 101]},
{a: 3, b: ['orange', 'banana', 'mango', 'apple'], c: [5, 10, 12, 14]},
{a: 4, b: ['banana', 'apple', 'mango', 'orange'], c: [2, 99, 101, 105]}
];
Upvotes: 2
Views: 290
Reputation: 386519
You could take the indices of the master array for sorting, sort them by the values of it and map all wanted array with a new order.
var array = [{ a: 1, b: ['apple', 'banana', 'orange', 'mango'], c: [42, 7, 18, 5] }, { a: 2, b: ['apple', 'banana', 'orange', 'mango'], c: [4, 101, 88, 3] }, { a: 3, b: ['apple', 'banana', 'orange', 'mango'], c: [14, 10, 5, 12] }, { a: 4, b: ['apple', 'banana', 'orange', 'mango'], c: [99, 2, 105, 101] }];
array.forEach(o => {
var indices = [...o.c.keys()].sort((a, b) => o.c[a] - o.c[b]);
['b', 'c'].forEach(k => o[k] = indices.map(i => o[k][i]));
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 198304
You can zip elements of b
and c
together, sort them by the c
element, then unpack them back. With this method, only one sort
is necessary, even if you are sorting multiple lists.
const arr = [
{a: 1, b: ['apple', 'banana', 'orange', 'mango'], c: [42, 7, 18, 5]},
{a: 2, b: ['apple', 'banana', 'orange', 'mango'], c: [4, 101, 88, 3]},
{a: 3, b: ['apple', 'banana', 'orange', 'mango'], c: [14, 10, 5, 12]},
{a: 4, b: ['apple', 'banana', 'orange', 'mango'], c: [99, 2, 105, 101]}
];
Object.values(arr).forEach(row => {
let sorting = row.b.map((e, i, a) => [e, row.c[i]]);
sorting.sort(([b1, c1], [b2, c2]) => c1 - c2);
row.b = sorting.map(([e, ]) => e);
row.c = sorting.map(([, e]) => e);
});
console.log(arr);
Upvotes: 2
Reputation: 370619
For each object, construct a Map
whose keys are fruit strings and values are the associated original number in the c
array. Sort the c
array, then sort the b
array based on the difference between the items in the map:
const arr = [
{a: 1, b: ['apple', 'banana', 'orange', 'mango'], c: [42, 7, 18, 5]},
{a: 2, b: ['apple', 'banana', 'orange', 'mango'], c: [4, 101, 88, 3]},
{a: 3, b: ['apple', 'banana', 'orange', 'mango'], c: [14, 10, 5, 12]},
{a: 4, b: ['apple', 'banana', 'orange', 'mango'], c: [99, 2, 105, 101]}
];
Object.values(arr).forEach(({ b, c }) => {
const fruitValues = c.reduce(
(map, num, i) => map.set(b[i], num),
new Map()
);
c.sort((a, b) => a - b);
b.sort((a, b) => fruitValues.get(a) - fruitValues.get(b));
});
console.log(arr);
Upvotes: 2