BLU
BLU

Reputation: 61

how to sort array of objects based on id and name

I want to sort Below array based on name,receiver_id,sender_id and role_id

this.role_id = 3
this.Data = [
    {receiver_id: 3,sender_id:4,name: 'john',},
    {receiver_id: 4,sender_id:3,name: 'james'},
    {receiver_id: 2,sender_id:3,name: 'jane'},
    {receiver_id: null,sender_id:null,name: 'charles'},
    {receiver_id: null,sender_id:null,name: 'aaron'},
    {receiver_id: 2,sender_id:4,name: 'alex'},
    {receiver_id: 3,sender_id:2,name: 'david'},
];

I want array objects with receiver_id == role_id or sender_id == role_id to be on top of array and also it should be in alphabetical order. like this

this.Data = [
    {receiver_id: 3,sender_id:2,name: 'david'},
    {receiver_id: 4,sender_id:3,name: 'james'},
    {receiver_id: 2,sender_id:3,name: 'jane'},
    {receiver_id: 3,sender_id:4,name: 'john'},
    {receiver_id: null,sender_id:null,name: 'aaron'},
    {receiver_id: 2,sender_id:4,name: 'alex'},
    {receiver_id: null,sender_id:null,name: 'charles'},
];

as of now I can sort based on name only

let colName = 'name'
this.Data.sort((b, a) => a[colName] < b[colName] ? 1 : a[colName] > b[colName] ? -1 : 0)

how to do this?

Upvotes: 0

Views: 896

Answers (4)

DeVeenix
DeVeenix

Reputation: 1

You can first sort them after thier "sender_id" and then iterrate over them and sort Alphabetically. Note that the code below is not perfect an can probably writtern more efficent.

Example:

 function sort(array) {
 // returns function if array is undefined or empty
 if(!array) return;

 let finalList = [];

 let swapped = false;

 do {
     swapped = false;

     for(let i = array.length - 1; i > 0; i--) {
         if(array[i].sender_id < array[i - 1].sender_id) {
             let temp = array[i];
             array[i] = array[i - 1];
             array[i - 1] = temp;

             swapped = true;
         }
     } 
 } while (swapped);

 // sorts alphabetic
 let lastBucket = [];
 let lastId = 1;

 for(entry in array) {
     if(array[entry].sender_id > lastId) {
         lastId = array[entry].sender_id;
         let swapped = false;

         do {
             swapped = false;

             for(let i = lastBucket.length - 1; i > 0; i--) {
                 if(lastBucket[i].name < lastBucket[i - 1].name) {
                     let temp = lastBucket[i];
                     lastBucket[i] = lastBucket[i - 1];
                     lastBucket[i - 1] = temp;
                     swapped = true;
                 }
             }

             for (item in lastBucket) {
                 finalList.push(lastBucket[item]);
             }

             lastBucket = [];
         } while(swapped);
     }
     lastBucket.push(array[entry]);
 }

 for(item in lastBucket) {
     finalList.push(lastBucket[item]);
 }

 return finalList;
 
 }

 // Test data
 const sampleArray = [
 {
     sender_id: 1,
     name: "test"
 },
 {
     sender_id: 3,
     name: "abc"
 },
 {
     sender_id: 2,
     name: "acd"
 },
 {
     sender_id: 1,
     name: "qqqqq"
 },
 {
     sender_id: 9,
     name: "hello world"
 },
 {
     sender_id: 1,
     name: "abc"
 }
 ]
 let sorted = sort(sampleArray);

Upvotes: 0

danh
danh

Reputation: 62676

It might help to factor the conditions into functions. vip means the object satisfies the numerical test. The other key idea is that vip sameness defaults to the alpha sort. This way we get the alpha sort amongst both vips and non-vips.

let role_id = 3
let data = [
    {receiver_id: 3,sender_id:4,name: 'john',},
    {receiver_id: 4,sender_id:3,name: 'james'},
    {receiver_id: 2,sender_id:3,name: 'jane'},
    {receiver_id: 2,sender_id:4,name: 'alex'},
    {receiver_id: 3,sender_id:2,name: 'david'},
];

function diff(a, b) {
  const vip = obj => (role_id === obj.receiver_id) || (role_id === obj.sender_id)
  const vipA = vip(a), vipB = vip(b)
  return vipA === vipB ? a.name.localeCompare(b.name) : (vipA ? -1 : 1)
}

console.log(data.sort(diff))

Upvotes: 1

JhonRM
JhonRM

Reputation: 215

You could try something like this:

this.Data.filter(a => (a.receiver_id === 3 || a.sender_id === 3))
         .sort((b, a) => a.name < b.name ? 1 : a.name > b.name ? -1 : 0)
    .concat(
this.Data.filter(a => !(a.receiver_id === 3 || a.sender_id === 3))
         .sort((b, a) => a.name < b.name ? 1 : a.name > b.name ? -1 : 0))

First, we filter only those entries which satisfy the condition receiver_id == role_id || sender_id == role_id, then we sort them by name.

We do the same for those entries which do not satisfy the condition. And finally we concatenate the two resulting arrays.

Upvotes: 0

Oscar Sales DEV
Oscar Sales DEV

Reputation: 476

With the sort method you determine if an item A goes before or after the other (B). First you need to define priorities, based on your description I guess:

1º: items where receiver_id == role_id || sender_id == role_id, ordered alphabetically

2º: items where receiver_id != role_id && sender_id != role_id, ordered alphabetically

That would be:

this.Data.sort( (a, b) => {

    let conditionForA = a.receiver_id == role_id || a.sender_id == role_id;
    let conditionForB = b.receiver_id == role_id || b.sender_id == role_id;

    if (conditionForA && !conditionForB) {
        // A > B
        return 1;
    }
    if (conditionForB && !conditionForA) {
        // B > A
        return -1;
    }

    // For now A = B, let's compare alphabetically
    if (a.name > b.name) return 1;
    else if (a.name < b.name) return -1;
    return 0; //equal

});

Upvotes: 0

Related Questions