-1

Here is an example an object with an array I want to sort:

{
  first: 'Zangief',
  second: 'Cammy'
  names: [
    {name: 'Dee Jay'},
    {name: 'Zangief'},
    {name: 'Dhalsim'}
    {name: 'Chun-Li'},
    {name: 'Blanka'},
    {name: 'Cammy'}
  ]
}

I want to have Zangief fixed on the first place and Cammy on the second place, and the rest is alphabetically ordered.

expected result:

[
    {name: 'Zangief'},
    {name: 'Cammy'},
    {name: 'Blanka'}
    {name: 'Chun-Li'},
    {name: 'Dee Jay'},
    {name: 'Dhalsim'},
]

I know this sorts the names alphabetically:

obj.names.sort((a,b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));

and then I could find the two names and put them to the first two places, but is there a sorting function, what could do this while sorting?

SherylHohman
  • 16,580
  • 17
  • 88
  • 94
user3568719
  • 1,036
  • 15
  • 33
  • final output is array of object? – brk Feb 20 '19 at 16:12
  • @brk yes, I edited my question – user3568719 Feb 20 '19 at 16:17
  • You can write your own custom sort function. If you don't want to do that, then you can remove those two items from the array. Sort the array, and convey to the first two items. Steps can be combined. Look up "JavaScript custom sort function". Or see this post: https://stackoverflow.com/questions/5002848/how-to-define-custom-sort-function-in-javascript – SherylHohman Feb 20 '19 at 17:17
  • 1
    Possible duplicate of [How to define custom sort function in javascript?](https://stackoverflow.com/questions/5002848/how-to-define-custom-sort-function-in-javascript) – SherylHohman Feb 20 '19 at 17:18

4 Answers4

1

You could probably just modify your function to be something like that:

obj.names.sort((a,b) => {
    if (a.name === obj.first || (a.name === obj.second && b.name !== obj.first)){
        return -1;
    }
    return (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0);
});
Lamonde
  • 138
  • 8
0

You could build an object with the order of known and unkown names and take the value for ordering.

If the value is the same, then sort by string.

var object = { first: 'Zangief', second: 'Cammy', names: [{ name: 'Dee Jay' }, { name: 'Zangief' }, { name: 'Dhalsim' }, { name: 'Chun-Li' }, { name: 'Blanka' }, { name: 'Cammy' }] },
    order = Object.assign(
        ...['first', 'second', ''].map((k, i) => ({ [object[k]]: i + 1 }))
    );

object.names.sort(({ name: a }, { name: b }) =>
    (order[a] || order.undefined) - (order[b] || order.undefined) || a.localeCompare(b)
);

console.log(object.names);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

Here's my 2 cents. I don't think it would be wise to hard code the names of the special names. I would add an order to your array that would cause the sort to override it's default ordering. So, then you wouldn't need the two properties first and second. If you are not able to modify the original array, then perhaps one of the other answers is more appropriate.

let object = {
    names: [
        { name: 'Dee Jay' },
        { name: 'Zangief', order: 1 },
        { name: 'Dhalsim' },
        { name: 'Chun-Li' },
        { name: 'Blanka' },
        { name: 'Cammy', order: 2 }
    ]
}

object.names.sort((a, b) => {
    return (a.order || Number.MAX_SAFE_INTEGER) - (b.order || Number.MAX_SAFE_INTEGER) 
           || a.name.localeCompare(b.name);

});

object.names.forEach(entry => console.log(entry.name));

Another possibility, even though I don't really like it would be to pre-process the array before the new sort. Something like this:

object.names.find( entry => entry.name === 'Zangief' ).order = 1;
object.names.find( entry => entry.name === 'Cammy' ).order = 2;
object.names.sort( /* new sort */ );

with the appropriate error checking added. Again, I don't like this but it's a possibility.

gkelly
  • 268
  • 1
  • 9
0

    let obj = {
      first: 'Zangief',
      second: 'Cammy',

      names: [
        {name: 'Dee Jay'},
        {name: 'Zangief'},
        {name: 'Dhalsim'},
        {name: 'Chun-Li'},
        {name: 'Blanka'},
        {name: 'Cammy'}
      ]
    };

    obj.names.sort((a,b) => {
      // exit early, (or trigger error if it should never happen)
      if (a.name === b.name) return 0;

      // No matter what, 'Zangief' gets moved to the front.
      if (a.name === obj.first) return -1;
      if (b.name === obj.first) return 1;

      // if no Zangief, 'Cammy' always moves forward.
      if (a.name === obj.second) return -1;
      if (b.name === obj.second) return 1;

      // otherwise, normal alphabetical sorting
      return (a.name > b.name) ? 1 : -1;
    });
    
console.log(obj.names);    

Alternatively, you can do a long "one-liner":
filter returns a new array with obj.first and obj.second removed.
sort then sorts that new array in place, according to the usual rules.
concat returns a new array appending this sorted array to [obj.first, obj.second], your "starting" array.

let obj = {
  first: 'Zangief',
  second: 'Cammy',

  names: [
    {name: 'Dee Jay'},
    {name: 'Zangief'},
    {name: 'Dhalsim'},
    {name: 'Chun-Li'},
    {name: 'Blanka'},
    {name: 'Cammy'}
  ]
};

let sorted = [{name: obj.first}, {name: obj.second}]
  .concat(obj.names.filter(item => (
    ((item.name !== obj.first) && 
     (item.name !== obj.second))
  )).sort((a, b) => (a.name > b.name)
      ? 1 
      : ((b.name > a.name) ? -1 : 0)
  ));

console.log(sorted);

// simplified data structure
const first = 'Zangief';
const second= 'Cammy';

const names = [
    'Dee Jay',
    'Zangief',
    'Dhalsim',
    'Chun-Li',
    'Blanka',
    'Cammy'
];

// filter/concat (version 2) does not alter original names array.    
let sorted = [first, second]
  .concat(names.filter(name => (
    !((name == first) || (name == second))
  )).sort());
  
console.log("new sorted array, (version 2) via filter/concat: \n", sorted);

// orig array untouched
console.log("original names array (untouched): \n", names);

// custom sort, (version 1) alters the original names array.
names.sort((a,b) => {
      // 'Zangief' gets moved to the front.
      if (a === first) return -1;
      if (b === first || b === second) return 1;

      // Othwerwise 'Cammy' moves forward.
      if (a === second) return -1;
//      if (b === second) return 1;

      // all other strings: normal alphabetical sorting
      return (a, b) => (a > b) ? 1 : ((b > a) ? -1 : 0)
    });
    
console.log("names array, altered, after (version 1) sorting", names);
SherylHohman
  • 16,580
  • 17
  • 88
  • 94