Home > Net >  How to sort an array in javascript keeping its sequence
How to sort an array in javascript keeping its sequence

Time:05-03

I have a scenario where I need to update an array in order to have random objects of the array sorted into other positions but I also need to keep a sequence of all the other elements in the array, I'll give an example of the array and what the output should be like:

let temp1 = [
  {id: 1, text: 'info1'},
  {id: 2, text: 'info2'},
  {id: 3, text: 'info3'},
  {id: 4, text: 'info4'},
  {id: 5, text: 'info5'}
]

Imagine I need to get the third and fifth elements and move them to the start of the array, I should have an output like this:

let output = [
  {id: 3, text: 'info3'},
  {id: 5, text: 'info5'}
  {id: 1, text: 'info1'},
  {id: 2, text: 'info2'},
  {id: 4, text: 'info4'}
]

I've tried a few samples I found online but none of them worked as expected since most of them just traded the elements from one place into another.

CodePudding user response:

Hate to loop over arrays several times, but I couldn't do a minimal amount of loops without writing complex code.

Right now, all I do is:

  1. loop over valueArr,
  2. which contains values for a certain property that you want to place first in temp1.
  3. I use the values from valueArr to find the index through itemArr.findIndex().
  4. That index is then used to splice temp1 and push the result in a new array.
  5. Finally, I merge the new array and the remaining items in temp1, which I return.

I added a parameter to determine which property in your items in temp1 that you want to "sort" by.

let temp1 = [
  {id: 1, text: 'info1'},
  {id: 2, text: 'info2'},
  {id: 3, text: 'info3'},
  {id: 4, text: 'info4'},
  {id: 5, text: 'info5'}
];
//                         'id'         [3, 5]     temp1
function placeFirstBasedOn(propertyStr, valueArr, itemArr) {
  let firstItems = [], index = 0;
  
  for (let value of valueArr) {  // 1
    index = itemArr.findIndex(item => item[propertyStr] === value); // 3
    firstItems.push( itemArr.splice(index, 1)[0] ); // 4
  }
  
  return firstItems.concat(itemArr);  // 5
}

console.log( placeFirstBasedOn('id', [3, 5], temp1) )

CodePudding user response:

Presented below is one possible way to achieve the desired objective.

Code Snippet

const sortKeepingSeq = (arr, priorityProp, priorityItemsList) => (
  structuredClone(arr)        // deep-clone to avoid mutating "arr"
  .map(                       // iterate to add priority/sequence-number
    (ob, seqNum) => ({ ...ob, seqNum })
  ).sort(                     // sort to achieve desired ordering of elements
    (                         // de-structure to directly access desired props
      {
        [priorityProp] : aval, seqNum : aseq
      }, {
        [priorityProp] : bval, seqNum : bseq
      }
    ) => {
      if (priorityItemsList.includes(aval)) {
        if (priorityItemsList.includes(bval)) {
          // both a and b are in the "priorityItemsList", so use seqNum to tie-break
          return aseq - bseq;
        } else {
          // b is not in priorityItemsList, so a takes priority
          return -1;
        }
      } else {
        if (priorityItemsList.includes(bval)) {
          // a is not in priorityItemsList, so b takes priority
          return 1;
        } else {
          // both a and b are NOT in the "priorityItemsList", so use seqNum to tie-break
          return aseq - bseq;
        }
      }
    }
  ).map(                      // iterate to "remove" the seqNum
    ({ seqNum, ...rest }) => ({...rest})
  )
);

const temp1 = [
  {id: 1, text: 'info1'},
  {id: 2, text: 'info2'},
  {id: 3, text: 'info3'},
  {id: 4, text: 'info4'},
  {id: 5, text: 'info5'}
];

console.log('sorted keeping sequence            
  • Related