简体   繁体   中英

JavaScript array of objects sort by specific property and then group by custom priority values

I have array of objects and my requirement was to group users by status (online users should come first) while sort grouped users by name. I am able to achieve result but here I am using lodash concat function separately. Can anyone help to use it along with chain function?

Code:

  import _ from 'lodash';

  const { online = [], offline = [] } = _.chain(users)
    .sortBy([(e) => _.toLower(e.name)])
    .groupBy((e) => e.status)
    .value();
  const result = _.concat(online, offline);
  console.log('grouped users sorted by name => ', result);

Input:

let users = [
    {
        'name': 'C',
        'status': 'online'
    },
    {
        'name': 'd',
        'status': 'online'
    },
    {
        'name': 'a',
        'status': 'offline'
    },
    {
        'name': 'b',
        'status': 'online'
    },
    {
        'name': 'f',
        'status': 'offline'
    },
    {
        'name': 'e',
        'status': 'offline'
    }
];

Output:

[
    {
        'name': 'b',
        'status': 'online'
    },
    {
        'name': 'C',
        'status': 'online'
    },
    {
        'name': 'd',
        'status': 'online'
    },
    {
        'name': 'a',
        'status': 'offline'
    },
    {
        'name': 'e',
        'status': 'offline'
    },
    {
        'name': 'f',
        'status': 'offline'
    }
]

Thanks

You can use reduce , filter & sort . Create a separate array and add the status in order you want the final array to be be. Then inside the reduce callback use filter to get the elements of that status and use sort to sort the elements in order of name

 let sortStatus = ['online', 'offline']; let users = [{ name: 'C', status: 'online' }, { name: 'd', status: 'online' }, { name: 'a', status: 'offline' }, { name: 'b', status: 'online' } ]; let data = sortStatus.reduce((acc, curr) => { acc.push( ...users .filter(item => item.status === curr) .sort((a, b) => a.name.localeCompare(b.name)) ); return acc; }, []); console.log(data);

You can do this easily without lodash too.

You can use a customized sort function when calling the sort() function of an array. Create a sort string including a 0 for online users and a 1 for offline users followed by the name. Then use this sort string in the comparison.

 let users = [{ 'name': 'C', 'status': 'online' }, { 'name': 'd', 'status': 'online' }, { 'name': 'a', 'status': 'offline' }, { 'name': 'b', 'status': 'online' }, { 'name': 'f', 'status': 'offline' }, { 'name': 'e', 'status': 'offline' } ]; users.sort((a, b) => { let sortStringA = (a.status.toUpperCase() == 'ONLINE' ? 0 : 1) + a.name.toUpperCase(); let sortStringB = (b.status.toUpperCase() == 'ONLINE' ? 0 : 1) + b.name.toUpperCase(); if (sortStringA < sortStringB) { return -1; } if (sortStringA > sortStringB) { return 1; } return 0; }); console.log(users);

If You can correct input:

 let users = [ { name: 'C', status: 'online' }, { name: 'd', status: 'online' }, { name: 'a', status: 'offline' }, { name: 'b', status: 'online' }, { name: 'f', status: 'offline' }, { name: 'e', status: 'offline' } ]; const sorted = users.sort((a, b) => { if (a.name.toLowerCase() < b.name.toLowerCase()) { return a.status.toLowerCase() < b.status.toLowerCase() ? 1 : -1; } return b.status.toLowerCase() < a.status.toLowerCase() ? -1 : 1;; }) console.log(sorted )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM