nick
nick

Reputation: 3227

Sort two arrays from object depending on one of those arrays in Javascript

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

Answers (3)

Nina Scholz
Nina Scholz

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

Amadan
Amadan

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

CertainPerformance
CertainPerformance

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

Related Questions