如何高效检查数组中是否存在指定用户名的Player对象?
问题描述
我有一个简单数组:
players = []
我想检查某个用户名是否已存在于数组中,存在就不添加该用户。但数组可能很大,遍历数组会影响性能,所以不想用遍历的方式。
我考虑过用字典(dict),但没试过,不确定能不能解决问题。
我的Player类定义如下:
class Player: def __eq__(self, other): return self._username == other._username def __init__(self, x, y, name, sprite): # 其他初始化逻辑
另外,我需要在两个不同的函数里访问这个存储用户的结构,之前用数组的时候,不确定能不能在另一个函数里用if character in players来检查。
以下是完整代码:
添加角色的函数
@commands.command(name='join') async def join(self, ctx: commands.Context): character = Player(random.randint(100, 400), 210, ctx.author.display_name, random.choice(["blue", "red"])) if character not in players: await ctx.send(f'You are in, {ctx.author.name}!') players.append(character) else: await ctx.send(f'You are already in, {ctx.author.name}!')
检查用户是否可参与任务的函数
@commands.command(name='quest') async def quest(self, ctx: commands.Context): # 检查玩家是否已加入游戏 print(players) await ctx.send(f'{ctx.author.name} joined the quest!')
有没有更好的实现方式?
解决方案
用字典确实是解决这个问题的最优方案,因为字典的键查询是O(1)时间复杂度,比数组遍历O(n)高效太多,尤其是数据量大的时候。
具体实现步骤
- 替换存储结构:把
players从数组改成字典,用用户标识(推荐用Discord用户唯一ID,避免昵称重复)作为键,Player实例作为值:
# 初始化字典,替代原数组 players = {}
- 修改
join函数:
@commands.command(name='join') async def join(self, ctx: commands.Context): # 用用户ID作为键更稳妥,避免昵称重复 user_id = ctx.author.id if user_id not in players: character = Player(random.randint(100, 400), 210, ctx.author.display_name, random.choice(["blue", "red"])) players[user_id] = character await ctx.send(f'你已加入游戏,{ctx.author.name}!') else: await ctx.send(f'你已经在游戏里了,{ctx.author.name}!')
这里直接通过用户ID判断是否存在,无需依赖Player类的__eq__方法,查询效率拉满。
- 修改
quest函数:
@commands.command(name='quest') async def quest(self, ctx: commands.Context): user_id = ctx.author.id if user_id in players: await ctx.send(f'{ctx.author.name} 已加入任务!') else: await ctx.send(f'{ctx.author.name} 请先加入游戏!')
优势说明
- 性能高效:字典基于哈希表实现,键查询的时间复杂度是O(1),不管用户数量多少,判断存在性的速度都极快,完全解决数组遍历的性能问题。
- 使用简单:在不同函数中访问字典的方式和数组一样直观,直接用
键 in 字典就能完成检查。 - 唯一性保障:用用户ID作为键,能完全避免昵称重复导致的判断错误,确保每个用户的唯一性。
内容的提问来源于stack exchange,提问作者Saffe
相关产品推荐
相关产品推荐

