-3

I have an array with following items:

[
  { collectionID: 1, collectionName: 'All Day' },
  { collectionID: 2, collectionName: 'Evening' },
  { collectionID: 3, collectionName: 'Morning' },
  { collectionID: 4, collectionName: 'Memory' },
  { collectionID: 5, collectionName: 'Brain' },
  { collectionID: 6, collectionName: 'Heart' },
  { collectionID: 7, collectionName: 'Album' },
];

I need the array output in sorted ascending order but starting three items must be at top: Output needed

[
  { collectionID: 1, collectionName: 'All Day' },
  { collectionID: 3, collectionName: 'Morning' },
  { collectionID: 2, collectionName: 'Evening' },
  { collectionID: 7, collectionName: 'Album' },
  { collectionID: 5, collectionName: 'Brain' },
  { collectionID: 6, collectionName: 'Heart' },
  { collectionID: 4, collectionName: 'Memory' },
];

I have tried this sorting of array. Getting data in sorted format but require starting three items must be on top in given format described in example.

sortArray.sort((a, b) => {
  if (a.collectionName < b.collectionName)
    return -1;
  if (a.collectionName > b.collectionName)
    return 1;
  return 0;
});

But getting output

[
  { collectionID: 7, collectionName: 'Album' },
  { collectionID: 1, collectionName: 'All Day' },
  { collectionID: 5, collectionName: 'Brain' },
  { collectionID: 2, collectionName: 'Evening' },
  { collectionID: 6, collectionName: 'Heart' },
  { collectionID: 4, collectionName: 'Memory' },
  { collectionID: 3, collectionName: 'Morning' }
] 

So i require the output as mentioned. collectionName All Day, Morning, Evening must be in given order and on top always followed by remaining array items in sorted format.

pilchard
  • 12,414
  • 5
  • 11
  • 23
  • Output needed [ { collectionID: 1, collectionName: 'All Day' }, { collectionID: 3, collectionName: 'Morning' }, { collectionID: 2, collectionName: 'Evening' }, { collectionID: 7, collectionName: 'Album' }, { collectionID: 5, collectionName: 'Brain' }, { collectionID: 6, collectionName: 'Heart' }, { collectionID: 4, collectionName: 'Memory' } ] – Madhav Singh Mar 16 '23 at 17:04
  • 1
    Copy the array without these 3 elements, e.g. with `filter`. Sort the copy. Prepend the 3 elements. – jabaa Mar 16 '23 at 17:07
  • Tried that but not got the desired result (output) – Madhav Singh Mar 16 '23 at 17:10
  • 1
    You forgot step 1 (Copy the array without these 3 elements) and step 3 (Prepend the 3 elements) – jabaa Mar 16 '23 at 17:10
  • Can you provide example. – Madhav Singh Mar 16 '23 at 17:12

5 Answers5

0

Remove the first three items, sort the rest, then add the first three items back on. Edit: You're asking for the first three to be in a very specific order that isn't alphabetical. If you can guarantee the order then use the below, if not then write a sort filter that sorts in order 1, 3, 2.

function alphabeticalSort( a, b ) {
  if (a.collectionName < b.collectionName)
    return -1;
  if (a.collectionName > b.collectionName)
    return 1;
  return 0;
}

let a = [
  { collectionID: 1, collectionName: 'All Day' },
  { collectionID: 2, collectionName: 'Evening' },
  { collectionID: 3, collectionName: 'Morning' },
  { collectionID: 4, collectionName: 'Memory' },
  { collectionID: 5, collectionName: 'Brain' },
  { collectionID: 6, collectionName: 'Heart' },
  { collectionID: 7, collectionName: 'Album' },
];

let b = a.splice( 3 );

console.log( [ a[0], a[2], a[1], ...b.sort( alphabeticalSort ) ] );
Alex
  • 848
  • 6
  • 7
0

I think this is what you want

sortArray = [
        { collectionID: 6, collectionName: 'Heart' },
          { collectionID: 7, collectionName: 'Album' },
          { collectionID: 5, collectionName: 'Brain' },
          { collectionID: 2, collectionName: 'Evening' },
          { collectionID: 1, collectionName: 'All Day' },
          { collectionID: 4, collectionName: 'Memory' },
          { collectionID: 3, collectionName: 'Morning' }
        ] 
        result = [
        { collectionID: 1, collectionName: 'All Day' },
        { collectionID: 3, collectionName: 'Morning' },
        { collectionID: 2, collectionName: 'Evening' },
        ];
        sortArray.sort((a, b) => {
          if (a.collectionName < b.collectionName)
            return -1;
          if (a.collectionName > b.collectionName)
            return 1;
          return 0;
        });

        sortArray.forEach((el, i) =>{
        
          if(el.collectionName != 'All Day' && el.collectionName != 'Morning' && el.collectionName != 'Evening')
            result.push(el);
            });
          
        console.log(result);
Nbody
  • 1,168
  • 7
  • 33
0

You could take an object with order and default value for moving items to the end and sort then by value.

This approach works for unsorted items.

const
    order = { 'All Day': 1, Morning: 2, Evening: 3, default: Number.MAX_VALUE },
    data = [{ collectionID: 1, collectionName: 'All Day' }, { collectionID: 2, collectionName: 'Evening' }, { collectionID: 3, collectionName: 'Morning' }, { collectionID: 4, collectionName: 'Memory' }, { collectionID: 5, collectionName: 'Brain' }, { collectionID: 6, collectionName: 'Heart' }, { collectionID: 7, collectionName: 'Album' }];

data.sort((a, b) => 
    (order[a.collectionName] || order.default) - (order[b.collectionName] || order.default) ||
    a.collectionName > b.collectionName || -(a.collectionName < b.collectionName)
);

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • If i am creating collection with the same name and incremental number. Example collection1, collection2, .....collection10, collection11. So after colection9. the order of collection start showing before collection1. – Madhav Singh Mar 21 '23 at 13:52
  • you could sort by this value and add another logical OR with localCompare with options, like [this](https://stackoverflow.com/questions/15478954/sort-array-elements-string-with-numbers-natural-sort/45278933#45278933). – Nina Scholz Mar 21 '23 at 16:06
0

You can hardcode the items you'd like to always be up front and then concatenate the remaining items after sorting them. You can do this by removing those three items from your array first, then sorting the rest

const unsortedArray = [ { collectionID: 4, collectionName: 'Memory' },   { collectionID: 5, collectionName: 'Brain' },   { collectionID: 6, collectionName: 'Heart' },   { collectionID: 7, collectionName: 'Album' }] 

const sortedArray = unsortedArray.sort((a, b) => {
  if (a.collectionName < b.collectionName)
    return -1;
  if (a.collectionName > b.collectionName)
    return 1;
  return 0;
});

const finalArray = [{ collectionID: 1, collectionName: 'All Day' },  { collectionID: 3, collectionName: 'Morning' },  { collectionID: 2, collectionName: 'Evening' },  ...sortedArray];

console.info(finalArray);
Sam
  • 24
  • 3
0

Here is a solution. You need to exclude the top items, sort the rest of the items and then concatenate the top and rest items.

const items = [
  { collectionID: 6, collectionName: 'Heart' },
  { collectionID: 7, collectionName: 'Album' },
  { collectionID: 5, collectionName: 'Brain' },
  { collectionID: 2, collectionName: 'Evening' },
  { collectionID: 1, collectionName: 'All Day' },
  { collectionID: 4, collectionName: 'Memory' },
  { collectionID: 3, collectionName: 'Morning' }
];

const topCollectionNames = ['All Day', 'Morning', 'Evening']

const topItems = topCollectionNames.map(item => items.find(i => i.collectionName === item))

const restItems = items.filter(item => !topCollectionNames.includes(item.collectionName))
  .sort((a, b) => a.collectionName.localeCompare(b.collectionName));

const sortedArray = topItems.concat(restItems);

console.log(sortedArray);
Andrew
  • 630
  • 1
  • 5
  • 14
  • Yes, That the result i want. Any optimize way to acheive this – Madhav Singh Mar 16 '23 at 17:19
  • You can add a new field to your array (e.g. "sortOrder"), and put down numbers by which you can sort the entire array just once. This is a common practice in real-world applications when there is no unambiguous sorting rule. – Andrew Mar 16 '23 at 17:23