A .NET implementation of the Atlassian LexoRank algorithm.
$ dotnet add package Innoloft.LexoRankA .NET implementation of the Atlassian LexoRank algorithm. LexoRank is a ranking system that allows for efficient reordering of items in a list without requiring updates to other items.
LexoRank is a ranking system that uses lexicographically ordered strings to maintain item positions. Unlike traditional integer-based ranking systems, LexoRank allows you to insert items between any two existing items without updating other items in the list.
Base36 Encoding: LexoRank uses base36 (0-9, a-z) to represent rank values, providing a large namespace for positions.
Buckets: The system uses three buckets (0, 1, 2) to manage rebalancing. When a bucket becomes too dense with items, you can move items to another bucket to maintain spacing.
Between Operation: The core operation calculates a rank between two existing ranks by finding the lexicographic midpoint.
var rank1 = LexoRank.Min(); // "0|000000:"
var rank2 = LexoRank.Max(); // "0|zzzzzz:"
var middle = rank1.Between(rank2); // "0|hzzzzz:"
var next = middle.GenNext(); // "0|i00007:"
While LexoRank minimizes updates, you may need to rebalance when:
Rebalancing involves moving items to a different bucket or regenerating ranks with better spacing.
Install the package via NuGet:
dotnet add package Innoloft.LexoRank
using LexoRank;
// Get the minimum and maximum ranks
var min = LexoRank.Min();
var max = LexoRank.Max();
// Get the middle rank
var middle = LexoRank.Middle();
// Generate the next rank
var next = middle.GenNext();
// Generate the previous rank
var prev = middle.GenPrev();
// Calculate a rank between two ranks
var between = min.Between(max);
You can convert a DateTime to a LexoRank. This is useful for initializing ranks based on creation time.
var now = DateTime.UtcNow;
var rank = LexoRank.FromTimestamp(now);
If you are storing ranks as strings and want to calculate a new rank between two existing rank strings:
string prevRank = "0|000000:";
string nextRank = "0|zzzzzz:";
// Calculate rank between prev and next
var newRank = LexoRank.CalculateBetween(prevRank, nextRank);
// Calculate rank at the beginning (before nextRank)
var startRank = LexoRank.CalculateBetween(null, nextRank);
// Calculate rank at the end (after prevRank)
var endRank = LexoRank.CalculateBetween(prevRank, null);
LexoRank uses buckets to manage rebalancing. This implementation supports the standard 3 buckets (0, 1, 2).
// Get the bucket of a rank
var bucket = rank.Bucket;
// Move to the next bucket
var nextBucketRank = rank.InNextBucket();
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)MIT