题目描述

给定 n 个服务器的名称与 IP 地址映射,以及 m 条包含 IP 地址的 Nginx 配置命令。你需要根据命令中的 IP 地址,查找到对应的服务器名称,并将其作为注释追加到每条命令的末尾。

输入格式

  • 第一行包含两个整数 nm(1 <= n, m <= 1000),分别表示服务器的数量和命令的数量。
  • 接下来的 n 行,每行包含两个字符串 nameip,用空格隔开,代表服务器名称和 IP 地址(保证所有 IP 唯一)。
  • 接下来的 m 行,每行是一条配置命令,格式为 command ip;(注意 IP 末尾自带一个分号)。保证命令中的 IP 一定在前面的列表中存在。

输出格式

  • 依次输出处理后的 m 条命令。
  • 每条命令按原样输出,并在末尾追加 #name,其中 name 是该 IP 对应的服务器名称。

样例输入

1
2
3
4
5
2 2
main 192.168.0.2
replica 192.168.0.1
block 192.168.0.1;
proxy 192.168.0.2;
1
2
3
4
5
6
7
8
9
3 5
google 8.8.8.8
codeforces 212.193.33.27
server 138.197.64.57
redirect 138.197.64.57;
block 8.8.8.8;
cf 212.193.33.27;
unblock 8.8.8.8;
check 138.197.64.57;

样例输出

1
2
block 192.168.0.1; #replica
proxy 192.168.0.2; #main
1
2
3
4
5
redirect 138.197.64.57; #server
block 8.8.8.8; #google
cf 212.193.33.27; #codeforces
unblock 8.8.8.8; #google
check 138.197.64.57; #server

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
a,b = map(int, input().split())
server={}
for i in range(a):
current_name, current_ip = input().split()
server[current_name] = current_ip
for i in range(b):
command = input()
name,ip_semicolon = command.split()
ip , semicolon = ip_semicolon.split(';')
for annotate , address in server.items():
if ip==address:
print(f"{command} #{annotate}")

存在两个可以改进的点

  1. 遍历列表查找字典值对应的键,丧失了字典的“查找”特点,写for循环很C
  2. 用split处理字符串的时候不够优雅,很C

改进方案

1
2
3
4
5
6
7
8
9
10
11
a,b = map(int, input().split())
server={}
for i in range(a):
current_name, current_ip = input().split()
server[current_ip] = current_name
for i in range(b):
command = input()
name,ip_semicolon = command.split()
ip , semicolon = ip_semicolon.split(';')
annotate=server[ip]
print(f"{command} #{annotate}")

创建字典的时候,交换了键和值的位置,方便后续查找

对于split处理,在Python中有一下几种方式:

方案一:使用 rstrip()(最推荐,安全且语义清晰)

rstrip() 的作用是去掉字符串**右侧(末尾)**的指定字符。

1
2
3
4
5
# 我的写法
ip, semicolon = ip_semicolon.split(';')

# Pythonic 写法
ip = ip_semicolon.rstrip(';')

为什么好? 它的可读性极强,代码直接翻译过来就是“从右边剥离分号”。而且它很安全:如果字符串末尾没有分号,它什么也不会做,原样返回;

如果有多个分号(比如 192.168.0.1;;),它会一起剥离干净。

方案二:使用切片 [:-1](最常用,老司机的肌肉记忆)

如果你百分之百确定这个字符串的最后一个字符一定是分号,直接一刀切掉最后一个字符是最爽快的。

1
2
# Pythonic 写法
ip = ip_semicolon[:-1]

为什么好? 这是 Python 独有的“切片”魔法。:-1 表示“从开头一直取到倒数第一个字符(不包含倒数第一个)”。它执行速度极快,代码极简。缺点是如果格式不规范(比如末尾碰巧没分号),它会错误地把 IP 的最后一位数字给切掉。不过对于这道算法题来说,题目保证了格式,所以用切片完全没问题。

方案三:使用 removesuffix()(Python 3.9+ 专属,最精确)

这是 Python 3.9 之后专门为了“去掉后缀”加入的新方法。

1
2
# Pythonic 写法
ip = ip_semicolon.removesuffix(';')

为什么好? 它比 rstrip() 更严格。rstrip(';') 会去掉末尾所有的分号,而 removesuffix(';') 只会把 ';' 作为一个整体后缀去掉一次。它的语义是所有方案里最精准的。

所以后面部分可以改为

1
2
3
4
5
6
7
8
for _ in range(b):  # 如果变量 i 用不到,Python 里习惯用下划线 _ 代替
command = input()
# 直接用切片去掉最后一个分号,然后再切分出 IP
# 比如 "block 192.168.0.1;" -> "block 192.168.0.1" -> 拿到 "192.168.0.1"
clean_ip = command[:-1].split()[1]

# 查字典并输出
print(f"{command} #{server[clean_ip]}")