Python跨多列表名称匹配 实现无限层级关联账号遍历
问题描述
需要实现关联名称匹配功能:从输入搜索词出发,匹配所有名称包含该词的账号,再提取这些账号关联的所有名称,继续匹配对应账号,按该逻辑无层级限制遍历,最终返回所有关联的名称集合。
以提供的测试数据搜索charm为例,关联链路为:charm → 对应账号关联feline/voxela/derp/virgo → virgo对应账号关联bitten → bitten对应账号关联hello,示例预期返回关联名称范围为charm feline voxela derp virgo bitten hello。
当前编写的代码仅能遍历固定层数的关联关系,链路更长时会提前终止,无法返回全量关联结果。
现有代码
import json uids = {'483775843796': '"jared trav"','483843796': '"azu jared"', '483843996': '"hello azu"', '44384376': '"bitten virgo"', '48384326': '"bitten hello"', '61063868': '"charm feline voxela derp virgo"', '11136664': '"jessica"', '11485423': '"yukkixxtsuki"', '10401438': '"howen"', '29176667': '"zaku ramba char"', '36976082': '"bulma zelda dame prince"', '99661300': '"voxela"', '76923817': '"juniperrose"', '16179876': '"gnollfighter"', '45012369': '"pianist fuzz t travis blunt trav ttttttttttttttttttyt whole ryann lol tiper cuz"', '62797501': '"asriel"', '73647929': '"voxela"', '95019796': '"dao daoisms"', '70094978': '"mort"', '16233382': '"purrs"', '89270209': '"apocalevie waify"', '42873540': '"tear slash peaches attitude maso lyra juvia innocent"', '61284894': '"pup"', '68487075': '"ninja"', '66451758': '"az"', '23492247': '"vegeta"', '77980169': '"virus"'} def _whois(string): a = [] for i in uids: i = json.loads(uids[i]) i = i.split() if string in i: a += i for i in uids: i = json.loads(uids[i]) i = i.split() if bool(set(i) & set(a)) == True: a += i return list(set(a)) def whois(string): a = [] ret = _whois(string) for i in ret: a += _whois(i) return list(set(a)) print(whois("charm"))
问题根因
- 核心逻辑硬编码了遍历层数:
_whois仅做两轮固定匹配,外层whois仅对第一轮结果做一次二次匹配,总遍历深度不超过3层,超过3层的关联关系无法被覆盖 - 匹配过程中没有持续迭代新发现的关联名称:
_whois第二轮匹配时虽然会动态往结果集加新名称,但不会基于新加入的名称继续做下一轮匹配 - 存在重复解析开销:每次匹配都重复对UID对应的名称字符串做
json.loads和split操作,数据量大时性能差
修复方案
用广度优先搜索实现无层级限制的遍历,通过队列维护待匹配的名称,用集合去重并记录已发现的所有关联名称,循环直到队列中没有待匹配的名称为止,自动覆盖所有关联层级。
修复后代码
import json uids = {'483775843796': '"jared trav"','483843796': '"azu jared"', '483843996': '"hello azu"', '44384376': '"bitten virgo"', '48384326': '"bitten hello"', '61063868': '"charm feline voxela derp virgo"', '11136664': '"jessica"', '11485423': '"yukkixxtsuki"', '10401438': '"howen"', '29176667': '"zaku ramba char"', '36976082': '"bulma zelda dame prince"', '99661300': '"voxela"', '76923817': '"juniperrose"', '16179876': '"gnollfighter"', '45012369': '"pianist fuzz t travis blunt trav ttttttttttttttttttyt whole ryann lol tiper cuz"', '62797501': '"asriel"', '73647929': '"voxela"', '95019796': '"dao daoisms"', '70094978': '"mort"', '16233382': '"purrs"', '89270209': '"apocalevie waify"', '42873540': '"tear slash peaches attitude maso lyra juvia innocent"', '61284894': '"pup"', '68487075': '"ninja"', '66451758': '"az"', '23492247': '"vegeta"', '77980169': '"virus"'} # 预处理:提前解析所有UID对应的名称列表,避免重复计算 uid_alias_map = {} for uid, alias_str in uids.items(): uid_alias_map[uid] = json.loads(alias_str).split() def whois(search_keyword): related_aliases = set() check_queue = [search_keyword] while check_queue: current_key = check_queue.pop() if current_key in related_aliases: continue related_aliases.add(current_key) # 匹配所有包含当前关键词的账号 for aliases in uid_alias_map.values(): if current_key in aliases: # 将该账号下未处理过的别名加入待匹配队列 for alias in aliases: if alias not in related_aliases: check_queue.append(alias) return sorted(list(related_aliases)) # 测试 result = whois("charm") print(result)
运行上述代码搜索charm时,会自动遍历所有关联层级:从charm出发匹配到voxela、feline、derp、virgo,再通过virgo匹配到bitten,通过bitten匹配到hello,再通过hello匹配到azu,以此类推直到没有新的别名出现,完全满足全量关联匹配的需求。如果需要截断到某一层级,只需要在循环中增加层级计数判断即可。
内容的提问来源于stack exchange,提问作者Herenti
相关产品推荐
相关产品推荐

