如何从NUTS编码字符串列表中提取符合层级规则的目标字符串?
NUTS编码层级提取优化方案
问题背景
我有一个存储NUTS地域编码的字符串列表(示例:["SE","SE12","SE124"]),需要根据特定层级规则提取目标编码。
输入输出示例
输入示例:
input1 : ["SE", "SE123", "SE124", "SE123456", "SE123456789"], input2 : ["SE", "SE2", "SE123", "SE123456", "SE123456789"], input3 : ["SE", "SE123", "SE123456", "SE123456789"], input4 : ["SE","FI", "SE2"]
预期输出:
- output1 =>
"SE12" - output2 =>
"SE" - output3 =>
"SE123456789" - output4 =>
""
现有实现代码
public static string GetSpecificNuts(IList<string> nuts) { var outNuts = ""; var annNuts = nuts.Distinct().ToList(); if (annNuts.Any()) { if (annNuts.Count() == 1) { outNuts = annNuts.SingleOrDefault(); } else { var grouped = annNuts.GroupBy(n => n.Length).OrderByDescending(n=>n.Key).ToList(); var highest = grouped.Select(g => g.Key).FirstOrDefault(); var highestGroup = grouped?.SingleOrDefault(g => g.Key == highest)?.ToList(); var length = highestGroup?.Count; if (length == 1) { var highestNuts = highestGroup?.SingleOrDefault(); var contained = grouped?.Where(n => n.Key != highest).SelectMany(g => g.ToList()).Where(s => highestNuts.StartsWith(s)).OrderByDescending(s=>s.Length); var firstContained = contained.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(firstContained)) { outNuts = firstContained; } } while (length > 1) { var deducted = new List<string>(); highestGroup?.ForEach(i => { deducted.Add(i.Length > 2 ? i.Remove(i.Length - 1, 1) : i); }); var distinct = deducted?.Distinct().ToList(); length = distinct?.Count; highestGroup = distinct; if (length == 1) { outNuts = distinct?.SingleOrDefault(); } } } } return outNuts; }
规则说明
NUTS编码前2个字母为国家码,后续数字对应层级:
- 第1位数字 → 州组
- 第2位数字 → 州
- 第3位数字 → 地区
- 第4位数字 → 市镇(以此类推)
提取规则:
- 列表包含多个不同地区 → 取州编码
- 多个不同州 → 取州组编码
- 多个不同州组 → 取国家编码
- 包含多个国家编码 → 返回空字符串
- 若所有编码都属于同一最细层级 → 返回该层级编码
优化思路与重构实现
现有代码逻辑绕、可读性差,可从以下方向优化:
- 快速失败判断:先检查国家码数量,多国家直接返回空,避免无效计算
- 结构化层级处理:按从细到粗的层级(地区→州→州组→国家)依次验证,找到符合规则的第一个层级
- 简化前缀匹配:统一提取每个编码的各层级前缀,统计公共前缀的覆盖情况
重构后的代码
public static string GetSpecificNuts(IList<string> nuts) { // 去重并过滤无效编码(长度至少2,保证有国家码) var uniqueValidNuts = nuts.Distinct().Where(n => !string.IsNullOrWhiteSpace(n) && n.Length >= 2).ToList(); if (!uniqueValidNuts.Any()) return ""; // 提取所有国家码,多国家直接返回空 var countryCodes = uniqueValidNuts.Select(n => n.Substring(0, 2)).Distinct().ToList(); if (countryCodes.Count > 1) return ""; string countryCode = countryCodes[0]; // 提取所有编码的数字部分(去掉国家码),补全空字符串(对应纯国家码的情况) var numericParts = uniqueValidNuts.Select(n => n.Length > 2 ? n.Substring(2) : "").ToList(); // 定义层级:从细到粗,每个层级对应数字部分的长度 // 层级顺序:市镇(4) → 地区(3) → 州(2) → 州组(1) → 国家(0) var levels = new[] {4, 3, 2, 1, 0}; foreach (var level in levels) { // 提取当前层级的前缀(数字部分取前level位,加上国家码) var currentPrefixes = numericParts.Select(np => level == 0 ? countryCode : countryCode + np.Substring(0, Math.Min(np.Length, level)) ).Distinct().ToList(); // 如果当前层级只有一个公共前缀,检查下一层级是否有多个不同值 if (currentPrefixes.Count == 1) { string currentPrefix = currentPrefixes[0]; // 下一层级长度(比当前细一级) int nextLevel = level + 1; // 提取所有编码的下一层级前缀 var nextPrefixes = numericParts.Select(np => nextLevel == 0 ? countryCode : countryCode + np.Substring(0, Math.Min(np.Length, nextLevel)) ).Distinct().ToList(); // 如果下一层级有多个不同值,说明当前层级是需要返回的结果 if (nextPrefixes.Count > 1) { return currentPrefix; } } } // 如果所有编码都属于同一最细层级,返回该层级编码 return uniqueValidNuts.OrderByDescending(n => n.Length).FirstOrDefault() ?? ""; }
优化点说明
- 快速失败:先判断多国家情况,直接返回空,减少不必要的计算
- 层级清晰:按从细到粗的顺序检查层级,逻辑直观,容易维护
- 前缀提取统一:通过数字部分的长度定义层级,避免复杂的字符串截取和循环
- 边界处理完善:覆盖了纯国家码、编码长度不足层级长度等边界情况
内容的提问来源于stack exchange,提问作者Mohamad Hammash
相关产品推荐
相关产品推荐

