Last active
August 30, 2022 01:25
-
-
Save wzulfikar/e6014c85b9bcbe6ec152880e6942cd3d to your computer and use it in GitHub Desktop.
Lexorank example in TS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sortBy from "lodash/sortBy"; // https://github.com/kvandake/lexorank-ts | |
import { LexoRank } from "lexorank"; | |
const cards = [ | |
{ id: 1, rank: "", flag: "0" }, // flag 0: first card, flag 1: last card. We use flag so we don't have to recalculate first and last card. | |
{ id: 2, rank: "", flag: "" }, | |
{ id: 3, rank: "", flag: "1" }, | |
]; | |
function parseRank(rank: string) { | |
const lexorank = LexoRank.parse(rank); | |
return { | |
prev: () => lexorank.genPrev().toString(), | |
next: () => lexorank.genNext().toString(), | |
}; | |
} | |
let stepper = 0; | |
function printOrder(title: string, cards: any) { | |
console.log( | |
`${++stepper}. ${title}:`, | |
sortBy(cards, (card) => card.rank) | |
.filter((card) => card.rank != "") | |
.map((card) => `${card.id}-${card.rank}`) | |
); | |
} | |
console.log( | |
"- initial order:", | |
cards.map((card) => card.id) | |
); | |
console.log( | |
"min/max/middle:", | |
LexoRank.min().toString(), | |
LexoRank.max().toString(), | |
LexoRank.middle().toString() | |
); | |
// Create first rank (eg. adding first card). We need to use `.middle` | |
// because it's possible that a new card will be moved to a position before l1. | |
const l1 = LexoRank.middle(); | |
cards[0].rank = l1.toString(); | |
printOrder("Create first rank", cards); // [1] | |
// Create second rank (eg. appending card) | |
const l2 = l1.genNext(); | |
cards[1].rank = l2.toString(); // current order: [1, 2] | |
printOrder("Create second rank", cards); // [1, 2] | |
// Create third rank | |
const l3 = l2.genNext(); | |
cards[2].rank = l3.toString(); | |
printOrder("Create third rank", cards); // [1, 2, 3] | |
// Move l3 to between l1 and l2 | |
cards[2].rank = l1.between(l2).toString(); | |
printOrder("Move l3 to between l1 and l2", cards); // [1, 3, 2] | |
// You can't move card to "in between" using `genNext` as it will move to the end of order. | |
// Example: move l1 between l3 and l2 using `l3.genNext()` | |
cards[0].rank = l3.genNext().toString(); | |
printOrder("Move l1 using `l3.genNext`", cards); // [3, 2, 1] | |
// Let's move l1 back to before l3. But now let's use `parse` to simulate | |
// parsing rank from database. | |
cards[0].rank = LexoRank.parse(cards[2].rank).genPrev().toString(); | |
cards[0].flag = "0"; // We know that l1 is now the first card, hence we assign the flag | |
printOrder("Move l1 before l3", cards); // [1, 3, 2] | |
// And move l3 to the end of list (after l2). Now we'll use our own `parseRank` function. | |
cards[2].rank = parseRank(cards[1].rank).next(); | |
cards[2].flag = "1"; | |
printOrder("Move l3 to end of list", cards); // [1, 2, 3] | |
// Create new card and put at the beginning of list | |
const firstCard = cards.find((card) => card.flag == "0")!; | |
firstCard.flag = ""; // Remove flag because we know it'll no longer be the first card | |
const newCard = { id: 4, rank: parseRank(firstCard.rank).prev(), flag: "0" }; | |
cards.push(newCard); | |
printOrder("Create new card and put at the beginning of list", cards); // [4, 1, 2, 3] | |
// Summary | |
// 1. Store in db: rank, flag | |
// 2. When reordering card, only affected card need to update the rank | |
// 3. When creating new card (hence appending it to the list), two values need to update: | |
// - Assign "last card" flag to the new card | |
// - Remove "last card" flag from the old card (if any) | |
// 4. When moving card to first order, two values need to update: | |
// - Assign "first card" flag to the moved card | |
// - Remove "first card" flag from the old card | |
// 5. Finding first and last card in a list can be O(1) because they're indexable |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output:
