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.
source to share
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; }
source to share
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;
source to share
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;
}
source to share