自己写:给一个人加分

👁️ 0 人浏览 💬 0 人评论 ❤️ 添加收藏

把 TODO 补完:给戊加 50 分,打出加完之后戊的分数戊的名次(从 1 开始;用 / 隔开)。

题面里已经写好一个**迷你 Redis**(class Mini)和一个当数据库用的 Store

Mini 的时间是**步数**:r.tick(n) 表示过了 n 秒(过期由它触发)
字符串   set(k, v, ex=秒) / get(k) / incr(k) / delete(k) / exists(k) / ttl(k)
结构     hset,hget,hlen / rpush,lrange,llen / sadd,scard
排行榜   zadd(k, 名字, 分) / zincrby / zscore / zcard
         zrevrange(k, a, b) 分高的在前|zrevrank(k, 名字) 名次从 0 起
淘汰     Mini(maxsize=n) 超过 n 个键就淘汰**最久没碰过**的,记在 r.evicted 里

Store    s.query(key) 取一行,**每取一次 s.reads 就加一**(用来数回源次数)
         里面只有 u1~u5 五个用户
class Mini:
    """一个够用的迷你 Redis。时间用**步数**走:tick(n) 表示过了 n 秒。"""

    def __init__(self, maxsize=0):
        self.d = {}          # 键 → 值
        self.exp = {}        # 键 → 到点的时刻(没设过期的不在这里)
        self.used = {}       # 键 → 最后一次被碰是第几回(淘汰要用)
        self.seq = 0         # 只增不减:每碰一次 +1
                             # ⚠️ 不能用 now —— 读一下并不会让时间前进
        self.now = 0
        self.maxsize = maxsize   # 0 表示不限;超了就淘汰最久没碰的那个
        self.evicted = []        # 被淘汰掉的键,按先后记下来

    # ── 时间 ──────────────────────────────────────────────────────────
    def tick(self, n=1):
        self.now = self.now + n
        for k in list(self.exp):
            if self.exp[k] <= self.now:
                self.d.pop(k, None)
                self.exp.pop(k, None)
                self.used.pop(k, None)

    def _touch(self, k):
        self.seq = self.seq + 1
        self.used[k] = self.seq

    def _evict(self):
        while self.maxsize and len(self.d) > self.maxsize:
            old = min(self.used, key=lambda k: (self.used[k], k))
            self.d.pop(old, None)
            self.exp.pop(old, None)
            self.used.pop(old, None)
            self.evicted.append(old)

    # ── 字符串 ────────────────────────────────────────────────────────
    def set(self, k, v, ex=None):
        self.d[k] = v
        self.exp.pop(k, None)
        if ex is not None:
            self.exp[k] = self.now + ex
        self._touch(k)
        self._evict()

    def get(self, k):
        if k not in self.d:
            return None
        self._touch(k)
        return self.d[k]

    def incr(self, k):
        self.d[k] = int(self.d.get(k, 0)) + 1
        self._touch(k)
        self._evict()
        return self.d[k]

    def delete(self, k):
        self.d.pop(k, None)
        self.exp.pop(k, None)
        self.used.pop(k, None)

    def exists(self, k):
        return k in self.d

    def ttl(self, k):
        """还能活几秒。没设过期返回 -1,键都不在返回 -2(和 Redis 一样)。"""
        if k not in self.d:
            return -2
        if k not in self.exp:
            return -1
        return self.exp[k] - self.now

    def dbsize(self):
        return len(self.d)

    # ── 哈希 / 列表 / 集合 ────────────────────────────────────────────
    def hset(self, k, f, v):
        self.d.setdefault(k, {})[f] = v
        self._touch(k)
        self._evict()

    def hget(self, k, f):
        self._touch(k)
        return self.d.get(k, {}).get(f)

    def hlen(self, k):
        return len(self.d.get(k, {}))

    def rpush(self, k, v):
        self.d.setdefault(k, []).append(v)
        self._touch(k)
        self._evict()

    def lrange(self, k, a, b):
        self._touch(k)
        return self.d.get(k, [])[a:b + 1] if b >= 0 else self.d.get(k, [])[a:]

    def llen(self, k):
        return len(self.d.get(k, []))

    def sadd(self, k, v):
        self.d.setdefault(k, set()).add(v)
        self._touch(k)
        self._evict()

    def scard(self, k):
        return len(self.d.get(k, set()))

    # ── 有序集合(排行榜用)──────────────────────────────────────────
    def zadd(self, k, member, score):
        self.d.setdefault(k, {})[member] = score
        self._touch(k)
        self._evict()

    def zincrby(self, k, member, delta):
        z = self.d.setdefault(k, {})
        z[member] = z.get(member, 0) + delta
        self._touch(k)
        return z[member]

    def zscore(self, k, member):
        return self.d.get(k, {}).get(member)

    def zcard(self, k):
        return len(self.d.get(k, {}))

    def _sorted(self, k):
        """分高的在前;分一样的按名字排,保证每次结果一模一样。"""
        z = self.d.get(k, {})
        return sorted(z, key=lambda m: (-z[m], m))

    def zrevrange(self, k, a, b):
        return self._sorted(k)[a:b + 1]

    def zrevrank(self, k, member):
        """从 0 开始的名次,不在里面返回 None。"""
        order = self._sorted(k)
        return order.index(member) if member in order else None


# ── 一个"慢的那份":每读一次就记一笔,用来数回源次数 ──────────────────
class Store:
    """当作数据库用。里面只有 u1~u5 这几个用户。"""

    def __init__(self):
        self.reads = 0
        self.rows = {"u1": "甲", "u2": "乙", "u3": "丙", "u4": "丁", "u5": "戊"}

    def query(self, key):
        self.reads = self.reads + 1
        return self.rows.get(key)
r = Mini()
for m, sc in (("甲", 90), ("乙", 70), ("丙", 95),
              ("丁", 88), ("戊", 60)):
    r.zadd("top", m, sc)
# TODO:给戊加 50 分
print(str(r.zscore("top", "戊")) + "/" + str(r.zrevrank("top", "戊") + 1))
提交你的答案
请登录后提交答案。
去登录
代码编辑器
Ctrl + Enter 运行
本次输入:
输出:

                        
👩‍🏫
AI
💬 题目评论

全部评论