Search code examples
javascriptarraysobjectjavascript-objects

Javascript: complicated sorting of an array of objects (Example and intended result in the post)


let's say that I have an array of objects that is structured like below:

let fruits = [
 {type: 'apple', count:1},
 {type: 'apple', count:2},
 {type: 'apple', count:3},
 {type: 'orange', count:2},
 {type: 'orange', count:3},
 {type: 'orange', count:4},
 {type: 'banana', count:3},
 {type: 'banana', count:4}
]

I am trying to sort the array first by 'type', and then by 'count'. However, I want to do it in batches. That is, the sorted array would first show the smallest count entries per each type of fruit, whose orders are sorted by 'type', and then second smallest count entries, etc...The result should be like below:

let fruits = [
 {type: 'apple', count:1},
 {type: 'banana', count:3},
 {type: 'orange', count:2},
 {type: 'apple', count:2},
 {type: 'banana', count:4},
 {type: 'orange', count:3},
 {type: 'apple', count:3},
 {type: 'orange', count:4}
]

One way I can think about is to create new arrays from the original array to include the lowest counts, second lowest counts, etc... and then use the arrays to create a new array in the intended order, but looks like this will be a complicated code and wondered what would be the better way to do this.

Any suggestions/ideas? Thanks a lot in advance!


Solution

  • You could sort the array in advance by

    • type ascending,
    • count ascending

    and then take an object for the order of same type as group and get an array of index, group and object.

    After sorting, map the object as result.

    let fruits = [{ type: 'apple', count: 1 }, { type: 'apple', count: 2 }, { type: 'apple', count: 3 }, { type: 'orange', count: 2 }, { type: 'orange', count: 3 }, { type: 'orange', count: 4 }, { type: 'banana', count: 3 }, { type: 'banana', count: 4 }],
        groups = Object.create(null),
        result = fruits
            .sort((a, b) => a.type.localeCompare(b.type) || a.count - b.count)
            .map((object, index) => ({ index, group: groups[object.type] = (groups[object.type] || 0) + 1, object }))
            .sort((a, b) => a.group - b.group || a.index - b.index)
            .map(({ object }) => object);
    
    console.log(result);
    .as-console-wrapper { max-height: 100% !important; top: 0; }