【发布时间】:2018-07-02 20:50:07
【问题描述】:
所以我有一个文本框,在文本更改事件中,我有旧文本和新文本,并希望了解它们之间的区别。在这种情况下,我希望能够使用一个删除功能和一个插入功能重新创建带有旧文本的新文本。这是可能的,因为文本框中的更改有几种可能性:
- 仅删除了文本(一个或多个使用选择的字符)- ABCD -> AD
- 仅添加了文本(一个或多个使用粘贴的字符)- ABCD -> ABXXCD
- 删除和添加文本(通过在同一操作中选择文本和输入文本)- ABCD -> AXD
所以我想拥有这些功能:
Sequence GetRemovedCharacters(string oldText, string newText)
{
}
Sequence GetAddedCharacters(string oldText, string newText)
{
}
我的序列类:
public class Sequence
{
private int start;
private int end;
public Sequence(int start, int end)
{
StartIndex = start; EndIndex = end;
}
public int StartIndex { get { return start; } set { start = value; Length = end - start + 1; } }
public int EndIndex { get { return end; } set { end = value; Length = end - start + 1; } }
public int Length { get; private set; }
public override string ToString()
{
return "(" + StartIndex + ", " + EndIndex + ")";
}
public static bool operator ==(Sequence a, Sequence b)
{
if(IsNull(a) && IsNull(b))
return true;
else if(IsNull(a) || IsNull(b))
return false;
else
return a.StartIndex == b.StartIndex && a.EndIndex == b.EndIndex;
}
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public static bool operator !=(Sequence a, Sequence b)
{
if(IsNull(a) && IsNull(b))
return false;
else if(IsNull(a) || IsNull(b))
return true;
else
return a.StartIndex != b.StartIndex && a.EndIndex != b.EndIndex;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
static bool IsNull(Sequence sequence)
{
try
{
return sequence.Equals(null);
}
catch(NullReferenceException)
{
return true;
}
}
}
额外说明:我想知道哪些字符被删除以及哪些字符被添加到文本中以获得新文本,以便我可以重新创建它。假设我有 ABCD -> AXD。 “B”和“C”是被删除的字符,“X”是被添加的字符。因此,GetRemovedCharacters 函数的输出为 (1, 2),GetAddedCharacters 函数的输出为 (1, 1)。 GetRemovedCharacters 函数的输出指的是旧文本中的索引,GetAddedCharacters 函数的输出指的是删除删除字符后的旧文本中的索引。
编辑:我想到了几个方向:
- 我创建的这段代码*返回受影响的序列 - 如果字符被删除,它返回旧文本中删除的字符序列;如果添加了字符,则返回新文本中添加的字符序列。删除和添加文本时,它不会返回正确的值(我自己不确定我想要它是什么)。
- 也许文本框中的
SelectionStart属性会有所帮助 - 更改文本后插入符号的位置。
*
private static Sequence GetChangeSequence(string oldText, string newText)
{
if(newText.Length > oldText.Length)
{
for(int i = 0; i < newText.Length; i++)
if(i == oldText.Length || newText[i] != oldText[i])
return new Sequence(i, i + (newText.Length - oldText.Length) - 1);
return null;
}
else if(newText.Length < oldText.Length)
{
for(int i = 0; i < oldText.Length; i++)
if(i == newText.Length || oldText[i] != newText[i])
return new Sequence(i, i + (oldText.Length - newText.Length) - 1);
return null;
}
else
return null;
}
谢谢。
【问题讨论】:
-
IsNull函数的用途是什么?如果您试图避免==null在operator==中引起的堆栈溢出,请使用ReferenceEqual(a, null)[或c# 7 中的a is null]。不要依赖于抛出这样的 NRE。此外,通常最好根据==定义!=(并根据Equals定义==,尽管如果您实际上覆盖Equals,请确保您是GetHashCode 反映了这一点) -
恐怕你严重低估了这个问题。查找“差异”以获取更多信息。也许您可以使用 KeyPress 等事件并监视剪贴板来减少整个问题。仅 Textchanged 将使您面临整个未稀释的差异挑战。有关问题的示例,请参阅here。
-
这三种变化的组合是唯一可能发生的事情吗?您没有添加
XX并删除D的ABCDE --> AXXBDE,但不在字符串中的同一位置? -
简单修剪两个字符串两端的所有共同点,剩下的是改变的位。