昨天遇到了一个编程难题,要求从两种分词结果中找出不一致的部分进行校对,难点主要在要对校对的部分进行做标记,而这些不一致的部分,可能是A包含B的,也可能是B包含A的,比如:
这里是一个示例,两个结果中,红框框起来的部分就是不一不一致的部分,如何将这些不一致的部分标记出来。
在这里采用这个方案:
1.首先遍历,如果一致,那么继续下一条,以A为准,一致的部分把它添加到新集合中;
2.遇到不一致的情况
1)如果A大于B,那么B指针后移,一直到两者一致为止;
2)如果B大于A,那么A指针后移,一直到两者一致为止;
这里的问题是,A指针后移的时候,也要注意把它的元素添加到新集合中。这两部分都放在while循环中,一直到一致时结束循环。在这个while循环里,首先添加一次A元素。
private void checked()
{
textBox4.Text = "";
// systemTxtResult和manualTxtResult分别保存读进来的两个文件的集合
List<string> systemTxtResult = new List<string>(ReadStringFromTxt(textBox1.Text+textBox2.Text));
List<string> manualTxtResult = new List<string>(ReadStringFromTxt(textBox1.Text+textBox3.Text));
// resultToFind是保存两个文件不一致的条目,带编号,并且保存结果文件,共三列
// onlyResult保存只有结果文件
// onlySystemWrithIndex只保存系统文件的列表,并且带序号
// onlySystemWithoutIndex只保存系统文件的列表,不带序号,这个主要是为了和结果文件进行一个返回检查
List<string> resultToFind = new List<string>();
List<string> onlyResult = new List<string>();
List<string> onlySystemWithIndex = new List<string>();
List<string> onlySystemWithOutIndex = new List<string>();
for (int i = 0; i < systemTxtResult.Count; i++)
{
textBox4.AppendText(i.ToString() + "\r\n");
// 两个文件某个词条不一致发现
if (systemTxtResult[i] != manualTxtResult[i])
{
//给定一个初始循环变量
int m = 0, s = 0;
// tempResultManual保存的是每个音节组成的集合,最后要组成一个完整词条,再赋值给resultToFind
List<string> tempResultManual = new List<string>();
string resultStr = "";
// 将不一致的两个词条split成数组
string[] arrayM = manualTxtResult[i].Split('/');
string[] arrayS = systemTxtResult[i].Split('/');
while (s < arrayS.Count() && m<arrayM.Count())
{
// 如果数组第一个元素是互相相同的,那么进行while循环,一直循环到找到不一样的数组元素为止
if (arrayM[m] == arrayS[s])
{
while (arrayM[m] == arrayS[s] && m < arrayM.Count() && s < arrayS.Count())
{
// 如果数组第一个元素是互相相同的,那么进行while循环,一直循环到找到不一样的数组元素为止
// 每循环一次,要把系统文件这一个数组元素添加到新的集合中
tempResultManual.Add(arrayS[s] + "/");
m++;
s++;
if (m >= arrayM.Count() - 1 || s >= arrayS.Count() - 1)
break;
}
}
else
{
//如果发现不同,首先添加一个初始标记 ,S
tempResultManual.Add("S");
//获取到现在不同的两个音节
string tempManualStr = arrayM[m];
string tempSystemStr = arrayS[s];
//先把现在的系统文件的音节添加到新集合
tempResultManual.Add(arrayS[s] + "/");
//循环进行词组next组合,一直组合到系统文件和人工标注一样为止
while (tempManualStr != tempSystemStr && m<arrayM.Count() && s<arrayS.Count())
{
// 如果系统音节的长度小于人工标注的长度,那么系统音节下标加1,再组合再对比。
if (tempSystemStr.Length < tempManualStr.Length)
{
s++;
//这时候因为系统下标变化了,所以系统音节要添加到新集合中
tempResultManual.Add(arrayS[s] + "/");
tempSystemStr += arrayS[s];
}
// 如果人工标注的长度小于系统音节的长度,那么人工标注下标加1,再组合再对比。
if (tempSystemStr.Length > tempManualStr.Length)
{
m++;
tempManualStr += arrayM[m];
}
}
// 对比结束,找到两边都一致的最后一个边界,那么最后加一个E标记
tempResultManual.Add("E");
//下标分别再加1
m++;
s++;
}
}
foreach (string str in tempResultManual)
{
resultStr += str;
}
resultToFind.Add(resultStr);
}
}
WriteStringFromTxt( textBox1.Text+ textBox5.Text, resultToFind);
}