How do I reassign a list (in typescript) based on a property of the "rank" object?

I am trying to create a function to reassign a list based on their rank property. For example: (my object has a different property)

var array=[
{id:1,rank:2},
{id:18,rank:1},
{id:53,rank:3},
{id:3,rank:5},
{id:19,rank:4},//this item
]

      

This element {id: 19, rank: 4} is now at 2d position. The array becomes

 item= { currentRank: 4; newRank: 2} //see below

    array=[
    {id:1,rank:3},
    {id:18,rank:1},
    {id:53,rank:4},
    {id:3,rank:5},
    {id:19,rank:2},
    ]

      

FYI: These elements are reordered after html drag & drop operation. So I'm trying to make a function to re-rank based on a ranked item. I know the new drop item and its early rank.

So far I've done the following, but it doesn't work for all cases:

public reorderArray(item: { currentRank: string; newRank: string }, array: { id: string, rank: string }[]): { id: string, rank: string } [] {


      let arr = array.map(a => Object.assign({}, a)).sort((a, b) => (parseInt(a.rank) - parseInt(b.rank))).slice();
      //To avoid to change the reference??
      let isOrdered = arr.every((element, index, array) => {
        return array[index + 1] ? element.rank + 1 == array[index + 1].rank : true
      });

  if (isOrdered && arr[0].rank == (1).toString()) {


    if (parseInt(item.currentRank) < parseInt(item.newRank)) {
      //on descend un élément dans la liste => +1 entre le currentRank et )le newRank
      for (let i = parseInt(item.currentRank); i < parseInt(item.newRank); i++) {
        arr[i].rank = (parseInt(arr[i].rank) - 1).toString();
      }
      arr[parseInt(item.currentRank)].rank = (parseInt(item.newRank)).toString();
    }
    else if (parseInt(item.currentRank) > parseInt(item.newRank)) {
      for (let i = parseInt(item.newRank); i < parseInt(item.currentRank); i++) {
        arr[i].rank = (parseInt(arr[i].rank) + 1).toString();
      }
      arr[parseInt(item.currentRank)].rank = (parseInt(item.newRank) + 1).toString();
    }
    return arr


  }
  else {
    alert("This list is not ordered");
  }
}

      

nb: if the array is incorrectly configured (rank 1,3,4 ...), the function does nothing.

+3


source to share


3 answers


You can use an array for splice and iterate over to adjust the range.



function changeRank(object) {
    ranks.splice(object.newRank - 1, 0, ranks.splice(object.currentRank - 1, 1)[0]);
    ranks.forEach(function (a, i) {
        a.rank = i + 1;
    });
}

var array = [{ id: 1, rank: 2 }, { id: 18, rank: 1 }, { id: 53, rank: 3 }, { id: 3, rank: 5 }, { id: 19, rank: 4 }],
    ranks = [];

array.forEach(a => ranks[a.rank - 1] = a);

console.log(array);
changeRank({ currentRank: 4, newRank: 2 });
console.log(array);
      

.as-console-wrapper { max-height: 100% !important; top: 0; }
      

Run code


+1


source


I think you may be approaching this the wrong way.

Why not go through all the elements, and then, if the rank is equal or high, then the current one increases its rank? Then, once you're done, set the rank for the updated element:



Something like that:

for(var x = 0; x < items.length; x++){
    if(items[x].rank >= item.newRank && items[x].rank <= item.currentRank){
        items[x].rank++;
    }
}
item.rank = item.newRank;

      

0


source


This logic should work. I did it with the concept of an array. Consider the array index as a rank.

if (new_rank < current_rank)
{
    item = arr[current_rank] 
    i = new_rank;  
    temp = arr[i]; 
    i++;

    while(i<current_rank)
    {
        temp1 = arr[i];
        arr[i] = temp;
        temp = temp1;
        i++;
    }

    arr[new_rank] = item;
}

else
{
    item = arr[current_rank] 
    i = new_rank; 
    temp = arr[i]; 
    i--;

    while(i>current_rank)
    {
        temp1 = arr[i];
        arr[i] = temp;
        temp = temp1;
        i--;
    }

    arr[new_rank] = item;
}

      

0


source







All Articles