discord.py - 特定角色排行榜前 10 名
discord.py - top 10 specific roles leaderboard
我想做的是建立一个排行榜,其中包含最多角色的人,例如:
member1 - 10
member2 - 7
member3 - 4
...
有效的主要代码是这样的:
data = []
for member in ctx.guild.members:
name, score = member.name, len(member.roles)
data.append((name,score))
data.sort(key=lambda t: t[1], reverse=True)
await ctx.send("Leaderboard")
for i, (name, score) in enumerate(data[:10]):
await ctx.send(f"{i+1}. {name} - {score}")
但是我不想算Member,Admin这个角色。所以我试着做了以下:
@client.command()
async def top(ctx):
data = []
mroles = []
final = []
banned = ['Admin','Member']
for member in ctx.guild.members:
for roles in member.roles:
name, score = member.name, roles.name
mroles.append(score)
for roles in mroles:
if roles in banned:
continue
else:
final.append(roles)
data.append((name,len(final)))
data.sort(key=lambda t: t[1], reverse=True)
await ctx.send("Leaderboard")
for i, (name, score) in enumerate(data[:10]):
await ctx.send(f"{i+1}. {name} - {score}")
但输出是一些疯狂的值和成员的名字 x2:
1. testuser - 16671
2. testuser - 16532
3. testuser2 - 16393
4. testuser2 - 16255
有线索吗?我烧了好几个小时,我无法让它发挥作用。
您永远不会重置 mroles
或 final
。结合嵌套的 for 循环,这会导致它塞满项目,并随着您的继续而快速增加。
这些名字也出现了多次,因为你的 data.append((name,len(final)))
在 for roles in member.roles
里面 运行 - 这意味着他们将在排行榜中为他们拥有的每个角色获得另一个条目。
这是一个快速的方法:
@client.command()
async def top(ctx):
data = []
banned_roles = {'Admin', 'Member'} # this should be a set, because speed
for member in ctx.guild.members:
total_role_count = len(member.roles)
# Uncomment this line if you don't want the "@everyone" role to be included. Yes, this is an actual role.
#total_role_count -= 1
# fast O(n) way to compute # of banned roles
# it finds the roles that are banned by intersecting the member's roles and the banned roles
# then take the length of that and subtract it from the total number
# you could probably also do this using `set.difference`
role_names = {role.name for role in member.roles}
banned_count = len(role_names.intersection(banned_roles))
data.append((member.name, total_role_count - banned_count))
data.sort(key=lambda t: t[1], reverse=True)
# instead of sending all the messages, send a big message with newlines in it
# this avoids the ratelimit of 5 messages every 5 seconds
text = '\n'.join([f"{i+1}. {name} - {score}" for i, (name, score) in enumerate(data[:10])])
await ctx.send(f'Leaderboard\n\n{text}')
我想做的是建立一个排行榜,其中包含最多角色的人,例如:
member1 - 10
member2 - 7
member3 - 4
...
有效的主要代码是这样的:
data = []
for member in ctx.guild.members:
name, score = member.name, len(member.roles)
data.append((name,score))
data.sort(key=lambda t: t[1], reverse=True)
await ctx.send("Leaderboard")
for i, (name, score) in enumerate(data[:10]):
await ctx.send(f"{i+1}. {name} - {score}")
但是我不想算Member,Admin这个角色。所以我试着做了以下:
@client.command()
async def top(ctx):
data = []
mroles = []
final = []
banned = ['Admin','Member']
for member in ctx.guild.members:
for roles in member.roles:
name, score = member.name, roles.name
mroles.append(score)
for roles in mroles:
if roles in banned:
continue
else:
final.append(roles)
data.append((name,len(final)))
data.sort(key=lambda t: t[1], reverse=True)
await ctx.send("Leaderboard")
for i, (name, score) in enumerate(data[:10]):
await ctx.send(f"{i+1}. {name} - {score}")
但输出是一些疯狂的值和成员的名字 x2:
1. testuser - 16671
2. testuser - 16532
3. testuser2 - 16393
4. testuser2 - 16255
有线索吗?我烧了好几个小时,我无法让它发挥作用。
您永远不会重置 mroles
或 final
。结合嵌套的 for 循环,这会导致它塞满项目,并随着您的继续而快速增加。
这些名字也出现了多次,因为你的 data.append((name,len(final)))
在 for roles in member.roles
里面 运行 - 这意味着他们将在排行榜中为他们拥有的每个角色获得另一个条目。
这是一个快速的方法:
@client.command()
async def top(ctx):
data = []
banned_roles = {'Admin', 'Member'} # this should be a set, because speed
for member in ctx.guild.members:
total_role_count = len(member.roles)
# Uncomment this line if you don't want the "@everyone" role to be included. Yes, this is an actual role.
#total_role_count -= 1
# fast O(n) way to compute # of banned roles
# it finds the roles that are banned by intersecting the member's roles and the banned roles
# then take the length of that and subtract it from the total number
# you could probably also do this using `set.difference`
role_names = {role.name for role in member.roles}
banned_count = len(role_names.intersection(banned_roles))
data.append((member.name, total_role_count - banned_count))
data.sort(key=lambda t: t[1], reverse=True)
# instead of sending all the messages, send a big message with newlines in it
# this avoids the ratelimit of 5 messages every 5 seconds
text = '\n'.join([f"{i+1}. {name} - {score}" for i, (name, score) in enumerate(data[:10])])
await ctx.send(f'Leaderboard\n\n{text}')