javascript - Hur man tilldelar om en lista (i typescript) baserat på en "rank"-objektproperty?


Jag försöker göra en funktion för att omfördela en lista baserat på deras rank-egenskap. Till exempel: (mitt objekt har andra egenskaper)

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

Detta objekt {id:19,rank:4} är nu på 2:a position. Arrayen blir

 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: Dessa objekt ordnas om efter en HTML drag & drop-operation. Så jag försöker göra en funktion för att tilldela nya rangordningar baserat på det dragna objektets rang. Jag vet det dragna objektets nya rang och dess gamla rang.

Hittills har jag gjort följande, men det fungerar inte i alla fall:

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: om arrayen inte är korrekt sorterad (rang är 1,3,4...), gör funktionen ingenting.

Svar #1

Du kan använda en array för att splitta och sedan iterera för korrigering av intervallet.

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; }

Svar #2

Jag tror att du kanske närmar dig detta på fel sätt.

Varför inte loopa igenom alla objekt och sedan, om rankingen är lika med eller större än den nuvarande, öka dess ranking? Sedan, när du är klar, sätt rankingen för det uppdaterade objektet:

Något sådant här:

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;