{"id":41996687,"url":"https://github.com/yddeng/sortedset","last_synced_at":"2026-01-26T01:06:04.048Z","repository":{"id":45515755,"uuid":"435387554","full_name":"yddeng/sortedset","owner":"yddeng","description":"自定义排序规则的 sortedset。采用skiplist实现","archived":false,"fork":false,"pushed_at":"2022-07-14T05:48:20.000Z","size":24,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-12T19:41:52.118Z","etag":null,"topics":["go","rank","redis","skiplist","sortedset","zset"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yddeng.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-12-06T06:39:54.000Z","updated_at":"2024-11-05T08:25:37.000Z","dependencies_parsed_at":"2022-09-26T21:01:13.499Z","dependency_job_id":null,"html_url":"https://github.com/yddeng/sortedset","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yddeng/sortedset","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yddeng%2Fsortedset","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yddeng%2Fsortedset/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yddeng%2Fsortedset/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yddeng%2Fsortedset/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yddeng","download_url":"https://codeload.github.com/yddeng/sortedset/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yddeng%2Fsortedset/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28763132,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T00:37:26.264Z","status":"ssl_error","status_checked_at":"2026-01-26T00:37:25.959Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","rank","redis","skiplist","sortedset","zset"],"created_at":"2026-01-26T01:06:02.493Z","updated_at":"2026-01-26T01:06:04.036Z","avatar_url":"https://github.com/yddeng.png","language":"Go","readme":"# sortedset\n\n- 自定义排序规则\n- 遍历有序集合中指定区间分数的成员\n- 通过索引区间返回有序集合指定区间内的成员\n- 获取排名前 N 的用户、翻页\n- 获取用户排名附近的用户\n\n\n```\nkey string , value 为实现排序接口的任意类型\n\ntype Key string\ntype Interface interface {\n\tLess(other interface{}) bool\n}\n```\n\n使用 map 和 skiplist 实现\n\nskiplist 跳表，它允许快速查询，插入和删除一个有序连续元素的数据链表。\n跳跃列表的平均查找和插入时间复杂度都是O(logn)。\n\n## 用法\n\n1. 获取用户附近排名. `radius = 10`\n    1) 通过 `GetRank` 获取当前用户的排名 rank。\n    2) 计算出区间 `[rank-radius: rank+radius]`,通过 `Range` 遍历。\n    \n2. 获取排名前 N 的用户. `zs.Range(1, N)`, 亦可实现翻页。\n\n3. 获取分数区间 `[s1:s2]` 的用户数量、用户。`range by score`.\n    1) 通过 `Search` 函数分别获取 s1,s2 的排名 r1,r2 ,仅返回将要插入的位置。\n    2) 计算用户数量： r1-r2 取绝对值。\n    3) 遍历区间用户： 通过 `Range` 遍历。\n   \n4. 指定用户分数加上增量。`increase by`.\n    1) 获取用户对象后移除\n    2) 用户对象加上分数后添加\n\n5. 获取大于、小于 `score` 的用户数量。`zs.Search` 实现。\n\n\n## Usage\n\n```go\ntype Score float64\n\nfunc (this Score) Less(other interface{}) bool {\n\treturn this \u003e= other.(Score)\n}\n\nfunc TestNew(t *testing.T) {\n\tzs := New()\n\t// add\n\tzs.Set(\"hello\", Score(2.2))\n\tzs.Set(\"world\", Score(5.5))\n\tzs.Set(\",\", Score(1.1))\n\tzs.Set(\"how\", Score(3.3))\n\tzs.Set(\"are\", Score(3.3))\n\tzs.Set(\"you\", Score(5.5))\n\n\tt.Log(zs.Len())                // 6\n\t// get rank by key\n\tt.Log(zs.GetRank(\"hello\"))     // 5\n\t// get value by key \n\tt.Log(zs.GetValue(\"hello\"))    // 2.2 true  \n\t// get key,value by rank\n\tt.Log(zs.Select(zs.Len()))     // , 1.1\n\n\t// update\n\tfmt.Println()\n\tzs.Set(\"hello\", Score(6.6))\n\t// range\n\tzs.Range(1, zs.Len(), func(rank int, key Key, value interface{}) bool {\n\t\tt.Log(rank, \" -- \", key, value.(Score))\n\t\treturn true\n\t})\n\n\t// delete\n\tfmt.Println()\n\tt.Log(zs.Delete(\"hello\"))\n\t// RevRange\n\tzs.RevRange(1, zs.Len(), func(rank int, key Key, value interface{}) bool {\n\t\tt.Log(rank, \" -- \", key, value.(Score))\n\t\treturn true\n\t})\n\n\t// search\n\tscore := Score(3.3)\n\tt.Log(zs.Search(zs.Len(), func(i Interface) bool {  // 3\n\t\treturn i.(Score) \u003e score\n\t}))\n\n\t// would be inserted\n\tt.Log(zs.WouldBeInserted(score))   // 5\n\n}\n```\n```go\ntype User struct {\n\tname  string\n\tlevel int\n\tscore int\n}\n\n/*\n\t分数从大到小排序\n\t分数相同，按照等级排序\n\t分数、等级都相同，按照名字排序\n*/\nfunc (this *User) Less(other interface{}) bool {\n\to := other.(*User)\n\tif this.score \u003e o.score {\n\t\treturn true\n\t} else if this.score == o.score \u0026\u0026 this.level \u003e o.level {\n\t\treturn true\n\t} else if this.score == o.score \u0026\u0026 this.level == o.level \u0026\u0026 this.name \u003e o.name {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc TestNew2(t *testing.T) {\n\tzs := New()\n\n\tzs.Set(\"u1\", \u0026User{name: \"u1\", level: 2, score: 30})\n\tzs.Set(\"u2\", \u0026User{name: \"u2\", level: 2, score: 40})\n\tzs.Set(\"u3\", \u0026User{name: \"u3\", level: 3, score: 30})\n\tzs.Set(\"u4\", \u0026User{name: \"u4\", level: 3, score: 30})\n\n\tzs.Range(1, zs.Len(), func(rank int, key Key, value interface{}) bool {\n\t\tt.Log(rank, \" -- \", key, value.(*User))\n\t\treturn true\n\t})\n}\n\n//    output\n//    sortedset_test.go:92: 1  --  u2 \u0026{u2 2 40}\n//    sortedset_test.go:92: 2  --  u4 \u0026{u4 3 30}\n//    sortedset_test.go:92: 3  --  u3 \u0026{u3 3 30}\n//    sortedset_test.go:92: 4  --  u1 \u0026{u1 2 30}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyddeng%2Fsortedset","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyddeng%2Fsortedset","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyddeng%2Fsortedset/lists"}