刚开始看这个标题,很容易被“爱丽丝×甘恩”“黑暗塔”“神秘博士×DC”这些关键词带走注意力。但如果把这一行当成一段待清洗的文本,你会发现它其实是一个很有意思的数据解析问题:一段话里同时包含了参与方、作品来源、强度等级、括号注释、交叉作品关系。想让程序自动判断谁占优,难点从来不是“谁更强”,而是怎么把非结构化的标题解析成程序能比较的结构化数据。
本文用 Visual Basic(VB / VB.NET)来实现一个“VB标准”解析与对比工具:先把原始标题拆成角色主体、作品来源、强度标签,再把“高1A+”“1B”这类标签转成同一套可比较的规则,最后通过命令行和 WinForms 两种方式验证。读完你不但能跑通一个完整示例,还会理解这类“看似一句话”的数据为什么要先建模再做比较。
1. 这篇文章真正要解决的问题
如果你只是用文本编辑器打开一个标题,会觉得很自然:左侧是爱丽丝×甘恩,右侧是博士×至暗骑士,括号里是作品来源,中间用“vs”连接。但让计算机处理时,问题立刻变多:
- “爱丽丝×甘恩”中间的“×”表示组合关系,不是乘法,也不是“更强”的语义。
- “博士 1B×至暗骑士 高1A”里到底是一个角色带两个标签,还是两个角色各自带标签?
- “高1A+”在字符串排序上并不一定排在“1B”后面。
- 括号出现在不同位置,程序怎么知道它是作品来源,还是对标签的补充说明?
这些问题不是某一种特定标题独有的。只要是跨世界观的角色比较、版本比较、榜单排名,都会遇到“字段边界不清、修饰词含义不统一、等级体系乱”的情况。不要急着写一个if left > right的暴力判断,而是要先回答三件事:
- 什么样的信息要进入数据模型?
- “标准”在这个项目里具体指什么?
- 不同标签之间如何转成同一个数值坐标?
这篇文章会把这三个问题都落地成 VB / VB.NET 代码。你不需要对角色背景有深入研究,也不需要认可具体比较结果,只要把它当成一个“基于规则解析的中文文本项目”来跑通就行。
适合阅读这篇文章的读者,包括四类人:
- 想用 VB / VB.NET 做文本解析或爬虫数据处理的人。
- 需要给榜单、评分、等级类数据设计标准模型的开发者。
- 遇到“同名字段不同来源、同类型数据不同口径”的数据工程新人。
- 单纯想拿一个有趣案例练手 WinForms 和正则表达式的人。
2. 核心概念:跨作品强度标签与“标准”的含义
2.1 “VB标准”中的 VB 是什么意思
标题里出现“『VB标准』”这四个字,在不同语境下有不同理解。玩游戏圈或者跨作品对战讨论的人,可能把它理解成某类“战力评分标准”;而做桌面开发的人看到 VB,首先会想到 Visual Basic。
本文不纠结这个缩写到底来自哪个圈子,而是采用一个更工程化的解释:无论规则来自哪套体系,只要最终能把“谁比谁强”翻译成程序里的确定性规则,它就是可执行的“标准”。
在代码里,“标准”至少应该包含三层:
- 数据标准:字段有哪些,字段边界是什么。
- 解析标准:遇到中文括号、英文括号、空格、×、+、高这些符号时怎么处理。
- 比较标准:同类标签按什么顺序比较,不同类标签是否可比较。
有标准,程序才能稳定运行。没有标准,今天能跑通,换一条新标题就会崩。
2.2 等级标签常见组成
“高1A+”“1B”这类标签,在选手榜和虚拟对战讨论中非常常见。它们通常不是纯数字,而是由多个部分拼起来:
| 组成部分 | 示例 | 说明 |
|---|---|---|
| 主档位 | 1A、1B | 表示大的强度区间 |
| 高位修饰 | 高 | 表示高一个级别或同档上限 |
| 同档修饰 | + | 表示同主档位里更高 |
| 跨作品连接符 | × | 表示角色或作品组合,不参与数值计算 |
容易踩坑的是:很多人会直接拿字符串排序去比“高1A+”和“1B”。字符串按字符逐个比较,“1B”的开头“1”和“1A+”一样,但第二位“B”大于“A”,所以“1B”在字符串顺序上会排在“1A+”后面。可如果按强度理解,“1A”通常高于“1B”,这时候字典序结果和强度结果正好相反。
因此不能直接String.Compare,必须先解析成结构化的TierInfo,再按自己定义的权重比较。
2.3 跨作品比较的前提:先做规范化
每个作品都有自己的世界观基准。有的作品里面“爆星”很常见,有的作品里“爆楼”已经是天花板。跨作品比较时,争议往往来自“参照物不同”。
对应到数据工程里,就是要做规范化(normalization)。举例:
- 同一角色不同版本:漫画版、动画版、游戏版、小说版,应当拆成不同的记录,而不是混在一个对象里。
- 同一作品不同阶段:前期、中期、完全体,应当允许挂多条等级记录。
- 不同来源的标签:
High 1A+和高1A+在语义上更接近,而不是把英文字符串和中文串当成完全无关东西。
在这篇文章的示例里,我不会去定义一套真实可用的“全作品无敌排名”,因为那需要维护大量事实数据。我只把规则限定在解析和比较层面:你传入什么样的映射表,程序就用什么样的标准输出。这样既保证了示例完整,也避免越界声称程序真的能解决所有跨作品争论。
3. 对象模型:从标题中提取结构化信息
3.1 字段设计
先把一条对战标题拆成下面的字段。
| 字段 | 示例取值 | 意思 |
|---|---|---|
| RawText | 爱丽丝×甘恩 高1A+(黑暗灵魂×黑暗塔) | 输入原样,便于回溯 |
| Name | 爱丽丝×甘恩 | 参战主体,可能是组合角色 |
| Verse | 黑暗灵魂×黑暗塔 | 括号里的作品来源 |
| TierLabel | 高1A+ | 原始强度标签 |
这里不要把“×”拆掉之后就扔掉。对于组合角色来说,爱丽丝×甘恩说明这场战斗是两名角色一起出现;对于组合宇宙来说,黑暗灵魂×黑暗塔说明采用了多个作品背景。保留原始文本很重要,否则后续要排查解析错误时,没法回到源头。
3.2 一条标题如何拆解
输入标题:
『VB标准』爱丽丝×甘恩 高1A+(黑暗灵魂×黑暗塔) vs 博士 1B×至暗骑士 高1A(神秘博士×DC)先按“vs”切成两段。注意“vs”前后可能有空格、全角空格,因此切分时要做 Trim。
左侧段:
爱丽丝×甘恩 高1A+(黑暗灵魂×黑暗塔)右侧段:
博士 1B×至暗骑士 高1A(神秘博士×DC)然后去掉括号,留下主体:
爱丽丝×甘恩 高1A+ 博士 1B×至暗骑士 高1A这时用正则表达式去匹配高?1[A-Z]\+?,可以把高1A+、1B这类标签先提出来。
右侧的“博士 1B×至暗骑士 高1A”存在歧义。如果设计者认为博士是“1B”,至暗骑士是“高1A”,那就应该把角色拆成两行,而不是把两个等级塞在同一个字段。真正进入数据库时,我会建议改为:
博士 1B(神秘博士×DC) 至暗骑士 高1A(神秘博士×DC)这样才符合一条记录对应一个主体的规范。
这个例子也说明:解析器能解决一部分问题,但数据源头保持干净更重要。
3.3 中间数据结果预览
解析完成后,得到的数据可以这样表示:
{ "left": { "name": "爱丽丝×甘恩", "verse": "黑暗灵魂×黑暗塔", "tier": "高1A+" }, "right": { "name": "博士", "verse": "神秘博士×DC", "tier": "1B" } }实际项目中使用 JSON、数据库表或内存对象都可以。核心点是:经过解析后,“谁vs谁”从一段文本变成了可以检索的字段。
4. VB.NET 解析器实现
4.1 环境准备
本文示例使用 VB.NET 控制台工程。版本选择上,使用 Visual Studio 2019/2022 或对应的 .NET SDK 均可;如果你习惯命令行,可以用下面命令创建工程:
dotnet new console -lang VB -n VBTierDemo cd VBTierDemo代码逻辑不依赖某个具体框架版本,老一点的 .NET Framework 4.x 工程同样可以运行,只需把代码复制到Program.vb并自行补齐工程文件即可。
4.2 完整的解析器代码
下面代码实现三件事:
- 使用正则提取括号中的作品来源。
- 去掉括号后,使用正则提取强度标签。
- 把主体名称取出来。
' File: Program.vb Imports System.Text.RegularExpressions Public Class EntryInfo Public Property Name As String = "" Public Property Verse As String = "" Public Property TierLabel As String = "" End Class Public Module EntryParser Public Function Parse(raw As String) As EntryInfo Dim result As New EntryInfo() raw = raw.Trim() ' 1. 提取括号里的作品来源,兼容中英文括号 Dim versePattern As String = "[((]([^))]+)[))]" Dim verseMatch As Match = Regex.Match(raw, versePattern) If verseMatch.Success Then result.Verse = verseMatch.Groups(1).Value End If ' 2. 去掉括号,避免括号内容影响等级识别 Dim clean As String = Regex.Replace(raw, versePattern, "") ' 3. 识别 高1A+ / 1B 这类标签 ' 规则:可选的“高”,然后是数字1,再是一个大写字母,最后是可选的+ Dim tierPattern As String = "高?1[A-Z]\+?" Dim tierMatch As Match = Regex.Match(clean, tierPattern) If tierMatch.Success Then result.TierLabel = tierMatch.Value result.Name = clean.Substring(0, tierMatch.Index).Trim() Else result.Name = clean.Trim() result.TierLabel = "<未识别>" End If Return result End Function End Module Module Program Sub Main() Dim title As String = "『VB标准』爱丽丝×甘恩 高1A+(黑暗灵魂×黑暗塔) vs 博士 1B×至暗骑士 高1A(神秘博士×DC)" Console.WriteLine("原始输入:" & title) Console.WriteLine() ' 按“vs”分割左右两方 Dim sides As String() = title.Split(New String() {" vs "}, StringSplitOptions.RemoveEmptyEntries) For i As Integer = 0 To sides.Length - 1 Dim info As EntryInfo = EntryParser.Parse(sides(i)) Console.WriteLine("第" & (i + 1).ToString() & "方:") Console.WriteLine(" 主体 = " & info.Name) Console.WriteLine(" 来源 = " & info.Verse) Console.WriteLine(" 档次 = " & info.TierLabel) Console.WriteLine() Next Console.WriteLine("解析完成,