推荐使用
mudder、mudderjs
视频简讲
www.youtube.com/watch?v=OjQ…
npm库
www.npmjs.com/package/mud…
www.npmjs.com/package/mud…
www.npmjs.com/package/lex… (一般)
rust库
crates.io/crates/mudd…
crates.io/crates/lexo… (实现不好)
github
github.com/fasiha/mudd…
github.com/kevinhu/mud…
公司实践
support.atlassian.com/jira/kb/und…
原理简单介绍:
通过字符串0-9a-z进行排序,而不是数字。也可以加入大写字母A-Z。 为什么使用字符串:因为字符串可以很长,有base36/62位长度,而且数据库可以根据字符串进行排序。
例:假如有两个排序值aa、bb,如果要插入一个中间值可以使用aan。 并且可以使用bucket来解决没有中间值可插入的情况,桶即在排序值插入0、1、2三个数之一,例:0|aa。 例子:假如有两个排序值且字符长度为2的情况下:0|aa、0|ab,没有中间值可以插入了,则可以把0|ab的桶值加1为1|ab,则0|aa、1|ab之间又可以插入新的中间值(例:0|ac)了
为什么只使用3个桶?chatgpt是这样说的: LexoRank 只用 3 个桶,是为了简单、高效、易维护。 桶是粗粒度的分区,3 个桶足够覆盖前、中、后逻辑,保证大部分插入操作都可以在桶内完成而无需跨桶。 如果你真的有大量频繁插入,增加桶数量是可行的,但实现复杂度会增加。
LeksoRanks based on three things:
- Strings are easy to sort alphabetically.
- Between two strings you can find the average (not always, and it is not so easy).
- If there is no way to find the average — you can use the buckets (sounds weird, yeah).
为什么不使用数字?
如果是列表排序值是按照1、2、3、4、5顺序排列的话,则每拖拽一个列表项,最差的情况需要对每一个列表的排序值在数据库里进行更新。
如果加大数字间隔,比如第一个为1,第二个为1000,则插入的整数中间值为(1+1000)/2=500,以此类推,中间值总有耗尽的那一刻。如果使用分数呢,情况也是如此。网上给出的方案是没有中间值时进行重排,并且最好定期重排。
相比之下,字符串的可插入中间值是海量的,如图所示:
在a和b之间允许插入的中间值会随着字符长度指数增长。
| 允许长度L | 可插入数量计算 | 结果 |
|---|---|---|
| 1 | "a" → "b" | 0 |
| 2 | 36^(2-1) = 36^1 | 36 |
| 3 | 36^2 + 36 | 1296 + 36 = 1,332 |
| 4 | 36^3 + 36^2 + 36 | 46656 + 1296 + 36 = 47,988 |
| 5 | 36^4 + 36^3 + 36^2 + 36 | 1679616 + 46656 + 1296 + 36 = 1,723,604 |
| ... | ||
| 36 | 36^35 + 36^34 + ... + 36 | 3,036,108,432,483,867,243,645,927,998,368,073,634,822,868,632,171,448,576 |
其它方案?
双向链表,缺点:更新操作繁琐,遍历查询,没有分页功能 juejin.cn/post/699997…
题外话:
如果你的数据量比较小而且可以在本地存储为json文件,在js端可以修改其元素位置并覆盖保存。
例:我们想把id=5的元素移动到index=1(第二个位置)
let arr = [
{ id: 1, name: 'A' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' },
{ id: 4, name: 'D' },
{ id: 5, name: 'E' }
];
// 1. 找到元素索引
const fromIndex = arr.findIndex(item => item.id === 5);
const toIndex = 1;
// 2. 删除该元素
const [element] = arr.splice(fromIndex, 1);
// 3. 插入到指定位置
arr.splice(toIndex, 0, element);
console.log(arr);
[
{ id: 1, name: 'A' },
{ id: 5, name: 'E' },
{ id: 2, name: 'B' },
{ id: 3, name: 'C' },
{ id: 4, name: 'D' }
]
其它资源:
总是把字符串长度保持在最小值的最佳实现:stackoverflow.com/questions/3…