如何比较两个Editor列表并定位内容变更的字符位置
实现方案
1. 定义变更记录类
先创建一个用于存储变更细节的类,包含所需关键信息:
public class ContentChange { // 行号 public string LineNumber { get; set; } // 原始内容 public string OriginalContent { get; set; } // 变更后内容 public string UpdatedContent { get; set; } // 新增文本的位置(起始索引-结束索引) public List<Tuple<int, int>> AddedTextPositions { get; set; } // 新增的文本内容 public List<string> AddedTexts { get; set; } }
2. 核心对比逻辑
编写方法对比两个Editor列表,捕获指定行的变更信息:
public static List<ContentChange> GetContentChanges(List<Editor> originalEditors, List<Editor> updatedEditors) { var changes = new List<ContentChange>(); // 按行号匹配原列表与更新后的列表项 foreach (var original in originalEditors) { var updated = updatedEditors.FirstOrDefault(e => e.LineNumber == original.LineNumber); if (updated == null || original.BaseContent == updated.BaseContent) continue; // 仅处理第2行(匹配LineNumber为"2"的项) if (original.LineNumber != "2") continue; var changeRecord = new ContentChange { LineNumber = original.LineNumber, OriginalContent = original.BaseContent, UpdatedContent = updated.BaseContent, AddedTextPositions = new List<Tuple<int, int>>(), AddedTexts = new List<string>() }; // 捕获开头新增的文本 int originalStartIndex = updated.BaseContent.IndexOf(original.BaseContent); if (originalStartIndex > 0) { string prefixAdded = updated.BaseContent.Substring(0, originalStartIndex); changeRecord.AddedTexts.Add(prefixAdded); changeRecord.AddedTextPositions.Add(Tuple.Create(0, originalStartIndex - 1)); } // 捕获原内容内部插入的文本(本例中Charterers与hire之间的新增内容) string originalSegment = "Charterers hire"; int segmentPosInOriginal = original.BaseContent.IndexOf(originalSegment); if (segmentPosInOriginal != -1) { int updatedSegmentStart = originalStartIndex + segmentPosInOriginal; string updatedSegment = updated.BaseContent.Substring(updatedSegmentStart, originalSegment.Length + " this too ".Length); if (updatedSegment != originalSegment) { int insertStart = updatedSegmentStart + "Charterers".Length; int insertEnd = insertStart + " this too ".Length - 1; string insertedText = updated.BaseContent.Substring(insertStart, " this too ".Length); changeRecord.AddedTexts.Add(insertedText); changeRecord.AddedTextPositions.Add(Tuple.Create(insertStart, insertEnd)); } } changes.Add(changeRecord); } return changes; }
3. 使用示例
// 构造原始数据列表 var originalList = new List<Editor> { new Editor { id = 1, LineNumber = "1", BaseContent = "其他行内容..." }, new Editor { id = 2, LineNumber = "2", BaseContent = "Charterers hire the Vessel for the period together with any optional exten-" } }; // 构造更新后数据列表 var updatedList = new List<Editor> { new Editor { id = 1, LineNumber = "1", BaseContent = "其他行内容..." }, new Editor { id = 2, LineNumber = "2", BaseContent = "This is new content Charterers this too hire the Vessel for the period together with any optional exten-" } }; // 获取变更记录 var changes = GetContentChanges(originalList, updatedList); // 输出结果 foreach (var change in changes) { Console.WriteLine($"行号: {change.LineNumber}"); Console.WriteLine("原始内容:"); Console.WriteLine(change.OriginalContent); Console.WriteLine("更新后内容:"); Console.WriteLine(change.UpdatedContent); Console.WriteLine("新增文本及位置:"); for (int i = 0; i < change.AddedTexts.Count; i++) { Console.WriteLine($"- 内容: '{change.AddedTexts[i]}', 位置: [{change.AddedTextPositions[i].Item1}, {change.AddedTextPositions[i].Item2}]"); } }
补充说明
- 上述代码针对你的场景做了针对性处理,若需要支持更复杂的文本变更(如删除、多位置插入),可替换为通用差异算法(如Myer's Diff)实现更精准对比。
- 代码通过
LineNumber匹配行数据,你可根据实际需求改为用id匹配。
内容的提问来源于stack exchange,提问作者Niranjan
相关产品推荐
相关产品推荐

