C#重构IndexOfAny方法:获取字符串中最先匹配的anyOf元素
重构C#字符串扩展方法IndexOfAny,获取最先匹配的子串
要实现同时返回首个匹配的索引和对应的子串,可以按以下方式修改扩展方法:
核心思路
- 不再只收集索引,而是同时保存子串和它在源字符串中的有效索引(即索引≥0的情况)
- 从有效匹配中找出索引最小的条目;如果多个子串索引相同,返回
anyOf集合中最先出现的那个 - 用C#的值元组(ValueTuple) 来同时返回索引和匹配子串,无需额外定义类
完整实现代码
using System; using System.Collections.Generic; using System.Linq; public static class StringExtensions { public static (int Index, string Match) IndexOfAnyWithMatch(this string source, IEnumerable<string> anyOf, StringComparison stringComparisonType = StringComparison.CurrentCultureIgnoreCase) { if (source == null) throw new ArgumentNullException(nameof(source)); if (anyOf == null) throw new ArgumentNullException(nameof(anyOf)); // 遍历所有子串,保存子串、对应有效索引及原集合中的顺序 var matches = anyOf .Select((subStr, index) => new { Substring = subStr, Position = source.IndexOf(subStr, stringComparisonType), OrderInAnyOf = index }) .Where(item => item.Position >= 0); // 过滤未匹配的子串 if (!matches.Any()) { return (-1, null); // 无匹配时返回(-1, null) } // 先按索引升序,再按原集合顺序升序,取第一个结果 var firstMatch = matches.OrderBy(item => item.Position) .ThenBy(item => item.OrderInAnyOf) .First(); return (firstMatch.Position, firstMatch.Substring); } } // 调用示例 public class Program { public static void Main() { List<string> anyOf = new List<string>(){ "at", "near", "by", "above" }; string source = "South Branch Raritan River near High Bridge at NJ"; var result = source.IndexOfAnyWithMatch(anyOf); if (result.Index != -1) { Console.WriteLine($"最先匹配的子串是:\"{result.Match}\",索引位置:{result.Index}"); // 输出:最先匹配的子串是:"near",索引位置:27 } else { Console.WriteLine("未找到任何匹配的子串"); } } }
关键细节说明
- 空值校验:添加对
source和anyOf的空值判断,避免空引用异常 - 同索引处理:通过
OrderInAnyOf记录子串在原集合中的顺序,当多个子串在同一位置匹配时,返回原集合中先出现的那个(比如source="abc",anyOf={"a", "ab"}时,会返回"a") - 比较规则兼容:保留原方法的
StringComparison参数,支持大小写忽略、文化相关等不同字符串比较规则
内容的提问来源于stack exchange,提问作者senzacionale
相关产品推荐
相关产品推荐

