Javascript [SOLVED]: Javascript Alphabetically sort and move all doubles to the end of array

Javascript [SOLVED]: Javascript Alphabetically sort and move all doubles to the end of array

Home Forums Scripting Javascript Tutorials Javascript [SOLVED]: Javascript Alphabetically sort and move all doubles to the end of array

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #245689

    Cloudy Point
    Keymaster

    QuestionQuestion

    I am trying to sort an array of objects by a property. I run:

    array.sort(function(a, b){
      var textA = a.name.toUpperCase();
      var textB = b.name.toUpperCase();
      return (textA < textB) ? -1 : (textA > textB) ? 1: 0
    });
    

    To alphabetically sort the array objects first and then I run an array.sort with a custom compare function as below:

    array.sort(function(a, b){
      if(a.name === b.name){
        return -1;
      }
      return 1;
    });
    

    It seems to work with anything object that does not have a duplicate, however, as soon as there are doubles it pushes them all to the end of the array instead of just the extras.

    Example:

    [
      {name: 'Amy'},
      {name: 'Amy'},
      {name: 'Clark'},
      {name: 'Clark'},
      {name: 'Dan'},
      {name: 'Dave'}
      {name: 'Joe'},
      {name: 'Joe'}
    ]
    

    Expected Output:

    • Amy
    • Clark
    • Dan
    • Dave
    • Joe
    • Amy
    • Clark
    • Joe

    Actual Result:

    • Dan
    • Dave
    • Amy
    • Amy
    • Clark
    • Clark
    • Joe
    • Joe

    Sort Code To try and get Expected Result

    array.sort(function(a,b){
      if(a.name === b.name){return -1}
    
      return 1;
    });
    

    I have a feeling the array.sort with a compare function can handle this however I keep playing with return values of 0, -1, 1 and cannot seem to get it to work fully as I would like.

    Update

    Expected Result Criteria:

    If an object has the same name the duplicate should go to the end of the array. For example if there are two ‘Amy’ one stays at the begining of the array and the duplicate goes to the end. So that all first occurrences of the names wil be at the begining of the array and all the doubles, triples etc will will be reordered each time at the end of the array. So that it could potentially arrange alhpabetical multiple items.

    Example:

    [
      {name: 'Amy'},
      {name: 'Amy'},
      {name: 'Clark'},
      {name: 'Clark'},
      {name: 'Clark'},
      {name: 'Dan'},
      {name: 'Dave'},
      {name: 'Joe'},
      {name: 'Joe'},
      {name: 'Joe'},
    ]
    

    Expected result:

    Amy
    Clark
    Dan
    Dave
    Joe
    Amy – Duplicate
    Clark – Duplicate
    Joe – Duplicate
    Clark – Had a third
    Joe – Had a third

    As you can see it orders the first occurrence of all names alphabetically. Then orders the second occurence alhpabetically, and then the third. Until all duplicates are resolved.

    After talking in comments it has come to my understanding that it cannot be done in an array.sort function alone. Sort alone with a compare function seems to be great for single or grouping doubles but not for putting doubles at the end of the array.

    I will continue to try on my own. Any help is greatly appreciated though. Thanks.

    #245690

    Cloudy Point
    Keymaster

    Accepted AnswerAnswer

    You could use sorting with map by using a temporary object with a hash table for the same group array. Take from it the length of the used array as group for sorting.

    The sorting happens with the group and index.

    The result is mapped with index of the sorted temporary array.

    Tge first part generates an array with an index of the original array and their group which is taken from pushing a value into the same group. Actually we need oly the array length after pushing of the group. If more items are in the same group, the items will be sorted later.

    [
        {
            index: 0, // Amy
            group: 1
        },
        {
            index: 1, // Amy
            group: 2
        },
        {
            index: 2, // Dan
            group: 1
        },
        {
            index: 3, // Joe
            group: 1
        },
        {
            index: 4, // Joe
            group: 2
        }
    ]
    

    The above given array is then sorted by group and index, both ascending.

    At the last part, a new array is mapped with the index value of the sorted array.

    var array = [{ name: 'Amy' }, { name: 'Amy' }, { name: 'Dan' }, { name: 'Joe' }, { name: 'Joe' }],
        groups = Object.create(null),
        result = array
            // this part is only necessary if the names should be in ascending order
            // for keeping the given order, remove the part until next comment
            .sort(function (a, b) {
                return a.name.localeCompare(b.name);
            })
            // remove until here, if necessary
            .map(function (a, i) {
                return { index: i, group: (groups[a.name] = groups[a.name] || []).push(0) };
            })
            .sort(function (a, b) {
                return a.group - b.group || a.index - b.index;
            })
            .map(function (o) {
                return array[o.index];
            });
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    Example for unsorted data.

    var array = [{ name: 'Joe', i: 0 }, { name: 'Dan', i: 1 }, { name: 'Amy', i: 2 }, { name: 'Joe', i: 3 }, { name: 'Amy', i: 4 }],
        groups = Object.create(null),
        result = array
            .map(function (a, i) {
                return {
                    index: i,
                    group: (groups[a.name] = groups[a.name] || []).push(0),
                    value: a.name
                };
            })
            .sort(function (a, b) {
                return a.group - b.group || a.value.localeCompare(b.value);
            })
            .map(function (o) {
                return array[o.index];
            });
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    Source: https://stackoverflow.com/questions/48024812/javascript-alphabetically-sort-and-move-all-doubles-to-the-end-of-array
    Author: Nina Scholz
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.