cup_of
cup_of

Reputation: 6697

Sort array of objects, add sorted index to each object, then return to original sorting

I have an array:

  const array = [
    { name: 'b' },
    { name: 'a' },
    { name: 'c' },
  ]

The goal here is to keep the same array but to add a new property on each object based on its position if the array was sorted:

  const array = [
    { name: 'b', sortIndex: 1 },
    { name: 'a', sortIndex: 0 },
    { name: 'c', sortIndex: 2 },
  ]

I came up with a plan to just sort the array based on the name. Then loop through it and add the index to get this:

 const array = [
   { name: 'a', sortIndex: 0 },
   { name: 'b', sortIndex: 1 },
   { name: 'c', sortIndex: 2 },
 ]

Then I would loop through the original array and do a findIndex against the sorted array to get the index but that seems like terrible code with so many loops and stuff. Any ideas on how to make this better?

export function setSortIndexes(series) {
  const clone = cloneDeep(series);
  const sorted = orderBy(clone, [
    (x) => (x.name ? x.name.toLowerCase() : null),
  ]);

  sorted.forEach((x, i) => {
    x.sortIndex = i;
  });

  series.forEach(x => {
    const index = sorted.findIndex((s) => s.name === x.name);

    if (index !== -1) {
      x.sortIndex = sorted[index].sortIndex;
    }
  });

  return series;
}

Upvotes: 0

Views: 1254

Answers (2)

Mister Jojo
Mister Jojo

Reputation: 22320

you can do that:
no need to duplicate objects (or some of its elements) in a new array. an array of pointers to these objects is sufficient

const array = 
  [ { name: 'b'} 
  , { name: 'a'} 
  , { name: 'c'} 
  ] 
array                  // create a new array  
  .map(o=>({o}))      // of pointers ( o ) to refer each array objects
  .sort((a,b)=>a.o.name.localeCompare(b.o.name)) // sort 
  .forEach((_,i,a)=>a[i].o.sortIndex = i )      // add the sortIndex attr 


console.log(array)

Upvotes: 1

Matt
Matt

Reputation: 74761

Create a temporary array to sort, including the original index.
Sort by the name field
Add index to the original object.

array
  .map((e, i) => ({ name: e.name, originalIndex: i }))
  .sort((a, b) => a.name.localeCompare(b.name))
  .forEach((e, i) => array[e.originalIndex].sortIndex = i)

Upvotes: 1

Related Questions