如何使用LINQ在指定位置替换特定子字符串而非全部匹配项?
解决指定位置缩写替换的LINQ实现方案
嘿,这个需求的核心痛点在于字符串是不可变的,而且如果从前往后替换,前面的操作会改变字符串长度,导致后续的位置偏移失效,所以得换个思路处理:
我们可以先把缩写列表按位置从后往前排序,再用LINQ的Aggregate方法来累积处理字符串,这样前面的替换就不会影响后面的位置了。而且还要额外做个校验,确保指定位置开始的子串确实是我们要替换的缩写,避免误替换其他位置的相同缩写。
完整代码实现
public class Abbreviation { public int Pos { get; set; } public string ShortName { get; set; } public string LongName { get; set; } } class Program { static void Main(string[] args) { List<Abbreviation> abbreviations = new List<Abbreviation>(); abbreviations.Add(new Abbreviation() { Pos = 28, ShortName = "exp.", LongName = "expression" }); abbreviations.Add(new Abbreviation() { Pos = 38, ShortName = "para.", LongName = "paragraph" }); abbreviations.Add(new Abbreviation() { Pos = 51, ShortName = "ans.", LongName = "answer" }); string test = "What is exp.? This is a test exp. in a para. contains ans. for a question"; // 核心LINQ处理逻辑 var result = abbreviations .OrderByDescending(x => x.Pos) // 从后往前处理,避免位置偏移 .Aggregate(test, (currentStr, abbr) => { // 校验指定位置是否确实是目标缩写,防止误替换 if (abbr.Pos + abbr.ShortName.Length <= currentStr.Length && currentStr.Substring(abbr.Pos, abbr.ShortName.Length) == abbr.ShortName) { return currentStr.Remove(abbr.Pos, abbr.ShortName.Length) .Insert(abbr.Pos, abbr.LongName); } return currentStr; }); Console.WriteLine(result); } }
代码说明
- 倒序排序:
OrderByDescending(x => x.Pos)确保我们先替换位置靠后的缩写,这样前面的替换操作不会改变后续需要处理的位置坐标。 - Aggregate累积处理:这个方法就像一个迭代器,每次用处理后的字符串作为下一次迭代的输入,完美适配这种需要逐步修改字符串的场景。
- 位置校验:添加的判断逻辑是为了防止因为字符串修改后(或者原字符串本身的问题)导致指定位置不是目标缩写的情况,避免错误替换。
运行这段代码后,输出结果会是:
What is exp.? This is a test expression in a paragraph contains answer for a question
可以看到,只有指定位置的exp.(第28位)、para.(第38位)、ans.(第51位)被替换了,开头的exp.?没有被改动,完全符合需求。
内容的提问来源于stack exchange,提问作者Snekithan
相关产品推荐
相关产品推荐

