[英]fuzzy string compare (check for shorthand matching) C#
我有两个字符串列表,如果当前索引处的字符串在第二个列表中(反之亦然),则该字符串将从每个列表中提取索引,该字符串不能完全匹配,或者可以是另一个列表的缩写,考虑这两个清单
List<string> aList = new List<string> { "Id", "PartCode", "PartName", "EquipType" };
List<string> bList = new List<string> { "PartCode", "PartName", "PartShortName", "EquipmentType" };
在上面的示例中,我想要从aList
索引:1,2,3
并从bList
索引bList
从索引1,2 aList
是显而易见的完全匹配的字符串,但有趣的一部分“EquipType”和“EquipmentType”,其匹配 becuse“EquipType”是“EquipmentType”的简写
但“零件名称” 不是 “PartShortName” 的简写 ,因此不需要有指标
这是我的代码
List<string> aList = new List<string> { "Id", "PartCode", "PartName", "EquipType" };// 1, 2 , 3
List<string> bList = new List<string> { "PartCode", "PartName", "PartShortName", "EquipmentType" };//0, 1 ,3
List<int> alistIndex = new List<int>();
List<int> blistIndex = new List<int>();
for (int i = 0; i < aList.Count; i++)
{
string a = aList[i];
for (int j = 0; j < bList.Count(); j++)
{
string b = bList[j];
string bigger, smaller;
int biggerCount, smallerCount;
if (a.Length > b.Length)
{
bigger = a; smaller = b;
biggerCount = a.Length ; smallerCount = b.Length ;
}
else
{
bigger = b; smaller = a;
biggerCount = b.Length; smallerCount = a.Length ;
}
int countCheck = 0;
for (int k = 0; k < biggerCount; k++)
{
if (smaller.Length != countCheck)
{
if (bigger[k] == smaller[countCheck])
countCheck++;
}
}
if (countCheck == smaller.Length)
{
alistIndex.Add(i);
blistIndex.Add(j);
res = true;
break;
}
else
res = false;
}
}
alistIndex.ForEach(i => Console.Write(i));
Console.WriteLine(Environment.NewLine);
blistIndex.ForEach(i => Console.Write(i));
Console.ReadKey();
上面的代码工作得很好,看起来与此解决方案非常相似
但是如果像这样改变第二个列表的顺序
List<string> bList = new List<string> { "PartCode", "PartShortName", "PartName", "EquipmentType" };
我会得到索引0、1和3(但我想得到0 2和3)
我应该检查每一对的距离并返回最小的距离吗? 还是我应该以其他方式工作
谢谢
ps我也找到了这个 GitHub,但我不知道它是否对我有用
我确实觉得您要尝试做的事不是一个好主意... Id是Idiotic的缩写,仅举一个例子:-)仍然...我想对Unicode进行一些实验。
现在,此代码将单词分解为大写字母。 PartName
为Part + Name
因为N
为大写。 它不支持ID
作为Identifier
(因为它应该是IDentifier
),但是它支持NSA
作为NotSuchAgency
:-)因此,首字母缩略词是可以的,而FDA
并不等同于FoodAndDrugAdministration
,所以带有连词的首字母缩略词是KO。
public static bool ShorthandCompare(string str1, string str2)
{
if (str1 == null)
{
throw new ArgumentNullException(nameof(str1));
}
if (str2 == null)
{
throw new ArgumentNullException(nameof(str2));
}
if (str1 == string.Empty)
{
return str2 == string.Empty;
}
if (object.ReferenceEquals(str1, str2))
{
return true;
}
var ee1 = StringInfo.GetTextElementEnumerator(str1);
var ee2 = StringInfo.GetTextElementEnumerator(str2);
bool eos1, eos2 = true;
while ((eos1 = ee1.MoveNext()) && (eos2 = ee2.MoveNext()))
{
string ch1 = ee1.GetTextElement(), ch2 = ee2.GetTextElement();
// The string.Compare does some nifty tricks with unicode
// like string.Compare("ì", "i\u0300") == 0
if (string.Compare(ch1, ch2) == 0)
{
continue;
}
UnicodeCategory uc1 = char.GetUnicodeCategory(ch1, 0);
UnicodeCategory uc2 = char.GetUnicodeCategory(ch2, 0);
if (uc1 == UnicodeCategory.UppercaseLetter)
{
while (uc2 != UnicodeCategory.UppercaseLetter && (eos2 = ee2.MoveNext()))
{
ch2 = ee2.GetTextElement();
uc2 = char.GetUnicodeCategory(ch2, 0);
}
if (!eos2 || string.Compare(ch1, ch2) != 0)
{
return false;
}
continue;
}
else if (uc2 == UnicodeCategory.UppercaseLetter)
{
while (uc1 != UnicodeCategory.UppercaseLetter && (eos1 = ee1.MoveNext()))
{
ch1 = ee1.GetTextElement();
uc1 = char.GetUnicodeCategory(ch1, 0);
}
if (!eos1 || string.Compare(ch1, ch2) != 0)
{
return false;
}
continue;
}
// We already know they are different!
return false;
}
if (eos1)
{
while (ee1.MoveNext())
{
string ch1 = ee1.GetTextElement();
UnicodeCategory uc1 = char.GetUnicodeCategory(ch1, 0);
if (uc1 == UnicodeCategory.UppercaseLetter)
{
return false;
}
}
}
else if (eos2)
{
while (ee2.MoveNext())
{
string ch2 = ee2.GetTextElement();
UnicodeCategory uc2 = char.GetUnicodeCategory(ch2, 0);
if (uc2 == UnicodeCategory.UppercaseLetter)
{
return false;
}
}
}
return true;
}
接着
List<string> aList = new List<string> { "Id", "PartCode", "PartName", "EquipType" };
List<string> bList = new List<string> { "PartCode", "PartName", "PartShortName", "EquipmentType" };
List<List<int>> matches = new List<List<int>>();
for (int i = 0; i < aList.Count; i++)
{
var lst = new List<int>();
matches.Add(lst);
for (int j = 0; j < bList.Count; j++)
{
if (ShorthandCompare(aList[i], bList[j]))
{
lst.Add(j);
}
}
}
请注意,结果是List<List<int>>
,因为您可能对aList
的单个单词有多个匹配项!
现在... ShorthandCompare
有趣的部分是它试图变得“智能”并处理非BMP Unicode字符(通过使用StringInfo.GetTextElementEnumerator
)并处理分解后的Unicode字符(可以通过以下方式在Unicode中获得ì
字符): i
+ \̀
,这就是它的二分法)。 它通过使用string.Compare
来string.Compare
这一点,与string.Equals
不同,它是Unicode感知的( string.CompareOrdinal
更类似于string.Equals
而不是Unicode感知的)。
bool cmp1 = ShorthandCompare("IdìoLe\u0300ss", "Idi\u0300oticLèsser"); // true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.