如何在C#数组中查找含特定字符的元素索引?能否用Array.IndexOf?
问题
我有一个存储Tag的字符串列表,每个Tag包含Line、Source、Target三部分,示例:L02_FTxx10_STxx5,其中L02对应Line,FTxx10对应Source,STxx5对应Target。我将每个Tag按下划线拆分为数组,再将Line、Source、Target分别存入对应列表。但Source在数组中的位置不固定,无法使用静态索引,例如另一个Tag示例:L02_word_word_FTxx10_word_STxx5。由于Source始终包含xx,因此我需要找到数组中第一个包含xx的字符串的索引。请问能否使用Array.IndexOf实现?如果可以,该如何操作?或者有没有其他方法?
我的代码如下:
foreach (string s in TagLijst) { int index = -1; string[] tempArr = s.Split('_'); index = Array.IndexOf(???); if (!Line.Contains(tempArr[0])) { Line.Add(tempArr[0]); } if (!Source.Contains(tempArr[index])) { Source.Add(tempArr[index]); } if (!Target.Contains(tempArr.Last())) { Target.Add(tempArr.Last()); } Array.Clear(tempArr); }
解决方案
1. 能否用Array.IndexOf实现?
不行,Array.IndexOf仅支持完全匹配的元素查找,无法直接根据“包含xx”的条件定位索引。如果硬要结合它使用,需要先遍历找到符合条件的元素,再用IndexOf取索引,这属于冗余操作,不如直接遍历找索引高效。
2. 推荐的实现方法
方法一:遍历数组找目标索引
直接循环数组元素,判断是否包含xx,找到第一个匹配项后记录索引,逻辑直观且兼容性强:
foreach (string s in TagLijst) { int sourceIndex = -1; string[] tempArr = s.Split('_'); // 遍历查找第一个包含xx的元素索引 for (int i = 0; i < tempArr.Length; i++) { if (tempArr[i].Contains("xx")) { sourceIndex = i; break; } } // 确保找到有效索引再执行后续操作 if (sourceIndex != -1) { if (!Line.Contains(tempArr[0])) { Line.Add(tempArr[0]); } if (!Source.Contains(tempArr[sourceIndex])) { Source.Add(tempArr[sourceIndex]); } if (!Target.Contains(tempArr.Last())) { Target.Add(tempArr.Last()); } } // 无需调用Array.Clear,局部变量tempArr会在循环结束后自动被回收 }
方法二:用LINQ简化代码
如果项目已引入LINQ,可以用FirstOrDefault快速定位目标元素,再通过Array.IndexOf获取索引,代码更简洁:
using System.Linq; // 需要引入该命名空间 foreach (string s in TagLijst) { string[] tempArr = s.Split('_'); var sourceElement = tempArr.FirstOrDefault(str => str.Contains("xx")); if (sourceElement != null) { int sourceIndex = Array.IndexOf(tempArr, sourceElement); if (!Line.Contains(tempArr[0])) { Line.Add(tempArr[0]); } if (!Source.Contains(sourceElement)) { Source.Add(sourceElement); } if (!Target.Contains(tempArr.Last())) { Target.Add(tempArr.Last()); } } }
注意:若数组存在多个含xx的元素,FirstOrDefault会取第一个;若未找到匹配元素,sourceElement为null,需判空避免报错。
方法三:LINQ直接获取索引(.NET Core 3.0+/NET 5+)
在新版本.NET中,可通过Select绑定元素与索引,直接筛选出目标索引:
using System.Linq; foreach (string s in TagLijst) { string[] tempArr = s.Split('_'); int sourceIndex = tempArr.Select((str, idx) => new { str, idx }) .FirstOrDefault(x => x.str.Contains("xx"))?.idx ?? -1; if (sourceIndex != -1) { if (!Line.Contains(tempArr[0])) { Line.Add(tempArr[0]); } if (!Source.Contains(tempArr[sourceIndex])) { Source.Add(tempArr[sourceIndex]); } if (!Target.Contains(tempArr.Last())) { Target.Add(tempArr.Last()); } } }
额外优化建议
- 移除
Array.Clear(tempArr):tempArr是循环内的局部变量,循环结束后会被GC自动回收,手动清空无意义。 - 改用
HashSet<string>存储Line/Source/Target:Contains方法的查找效率会从O(n)提升至O(1),若后续需要列表格式,再调用ToList()转换即可。
内容的提问来源于stack exchange,提问作者Beko
相关产品推荐
相关产品推荐

