1.需求:从两个字符串数组中找到最匹配的字符串

    比如有一个Excel表格,我用DataTable存储了他的列名,我放到了一个字符串数组之中
    然后这个表格的名字可能有序号,车站名,经度,纬度,高度
    有另一个表则是编号,绝缘节名称,绝缘节经度,绝缘节经度,纬度,高程
    他们都代表同一个意思
    所以需要用字符串 模糊?匹配算法,来找到最合适的那一个
    我之前写的代码是这样的
    太简单了,且是有问题的,因为我找到包含项直接就输出了

    1. //这一部分是自己预设的列名
    2. string[] id = new string[] { "数据编号", "编号", "序号" };
    3. string[] latname = new string[] { "纬度", "lat", "Lat", "Latitude", "latitude", "纬度(毫秒)" };
    4. string[] lngname = new string[] { "经度", "lon", "Lon", "Longtitude", "longtitude", "Lng", "经度(毫秒)" };
    5. string[] hgtname = new string[] { "高程", "hgt", "Hgt" };
    6. string[] kiloname = new string[] { "公里标", "里程" };
    7. string[] stationName = new string[] { "车站名", "车站名称" };
    8. string[] trackName = new string[] { "所在轨道名称" };
    9. string[] bear = new string[] { "航向角", "航向角(毫秒)" };
    10. string[] deltabear = new string[] { "增量航向角" };
    11. string[] tag = new string[] { "备注" };
    12. //这一部分是返回的列的真正名字
    13. string idc = ReturnColumnName(id, strColumns);
    14. string latc = ReturnColumnName(latname, strColumns);
    15. string lngc = ReturnColumnName(lngname, strColumns);
    16. string hgtc = ReturnColumnName(hgtname, strColumns);
    17. string kiloc = ReturnColumnName(kiloname, strColumns);
    18. string stac = ReturnColumnName(stationName, strColumns);
    19. string tc = ReturnColumnName(trackName, strColumns);
    20. string bearc = ReturnColumnName(bear, strColumns);
    21. string dbc = ReturnColumnName(deltabear, strColumns);
    22. string tagc = ReturnColumnName(tag, strColumns);
    23. //这一部分则是很简单的,将关键词和真正的列名比较,返回匹配的那一个
    24. public string ReturnColumnName(string[] keyword, string[] columnNames)
    25. {
    26. string temp = "";
    27. for (int i = 0; i < columnNames.Length; i++)
    28. {
    29. if (string.IsNullOrEmpty(temp))
    30. {
    31. for (int j = 0; j < keyword.Length; j++)
    32. {
    33. if (columnNames[i].Contains(keyword[j]))
    34. {
    35. temp = columnNames[i];
    36. break;
    37. }
    38. }
    39. }
    40. else
    41. {
    42. break;
    43. }
    44. }
    45. return temp;
    46. }

    我在网上看到一个好的用正则表达式来匹配的
    先记录一下

    1. if (!Regex.IsMatch(comboBox1.Text, @"(高端类|中端类|低端类)"))//产品类型格式验证
    2. {
    3. MessageBox.Show("产品类型格式不正确!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
    4. return;
    5. }//------例1
    6. if (!Regex.IsMatch(comboBox2.Text, @"\d(16|32|48|56)"))//线路类型格式验证
    7. {
    8. MessageBox.Show("线路类型格式不正确!", "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
    9. return;
    10. }//----例2

    例1是指只有括号中的三个字符串才能通过匹配
    \d代表整数—-例2是四个整数的匹配

    一些正则规则表

    字符描述
    \ 转义字符,将一个具有特殊功能的字符转义为一个普通字符,或反过来
    ^ 匹配输入字符串的开始位置
    $ 匹配输入字符串的结束位置
    * 匹配前面的零次或多次的子表达式
    + 匹配前面的一次或多次的子表达式
    ? 匹配前面的零次或一次的子表达式
    {n} n是一个非负整数,匹配前面的n次子表达式
    {n,} n是一个非负整数,至少匹配前面的n次子表达式
    {n,m} mn均为非负整数,其中n<=m,最少匹配n次且最多匹配m
    ? 当该字符紧跟在其他限制符(,+,?,{*n},{n,},{nm})后面时,匹配模式尽可能少的匹配所搜索的字符串
    . 匹配除“\n”之外的任何单个字符
    (pattern) 匹配pattern并获取这一匹配
    (?:pattern) 匹配pattern但不获取匹配结果
    (?=pattern) 正向预查,在任何匹配pattern的字符串开始处匹配查找字符串
    (?!pattern) 负向预查,在任何不匹配pattern的字符串开始处匹配查找字符串
    x|y 匹配xy。例如,‘z|food’能匹配“z”或“food”。‘(z|f)ood’则匹配“zood”或“food”
    [xyz] 字符集合。匹配所包含的任意一个字符。例如,‘[abc]’可以匹配“plain”中的‘a’
    [^xyz] 负值字符集合。匹配未包含的任意字符。例如,‘[^abc]’可以匹配“plain”中的‘p’
    [a-z] 匹配指定范围内的任意字符。例如,‘[a-z]’可以匹配’a’到’z’范围内的任意小写字母字符
    [^a-z] 匹配不在指定范围内的任意字符。例如,‘[^a-z]’可以匹配不在‘a’~‘z”内的任意字符
    \b 匹配一个单词边界,指单词和空格间的位置
    \B 匹配非单词边界
    \d 匹配一个数字字符,等价于[0-9]
    \D 匹配一个非数字字符,等价于[^0-9]
    \f 匹配一个换页符
    \n 匹配一个换行符
    \r 匹配一个回车符
    \s 匹配任何空白字符,包括空格、制表符、换页符等
    \S 匹配任何非空白字符
    \t 匹配一个制表符
    \v 匹配一个垂直制表符。等价于\x0b和\cK
    \w 匹配包括下划线的任何单词字符。等价于‘’[A-Za-z0-9_]’
    \W 匹配任何非单词字符。等价于‘[^A-Za-z0-9_]’

    之后key[]字符串数组和真实字符串数组columnNames[]之间匹配的代码
    即先利用正则表达式写入一个匹配项,然后可能会稍微处理的快一些

    1. public string ReturnColumnName2(string[] keyword, string[] columnNames)
    2. {
    3. string temp = "";
    4. string match = "";
    5. for(int j=0;j<keyword.Length-1;j++)
    6. {
    7. match += keyword[j] + "|";
    8. }
    9. match += keyword.Last();
    10. match = "("+match+")";
    11. for (int i = 0; i < columnNames.Length; i++)
    12. {
    13. if(!string.IsNullOrEmpty(temp))
    14. {
    15. break;
    16. }
    17. if(Regex.IsMatch(columnNames[i],@match))// @"(高端类|中端类|低端类)"))//如果匹配成功
    18. {
    19. var matchCollection = Regex.Matches(columnNames[i], match);
    20. int index=columnNames.FindIndex(a => a.Contains(matchCollection[0].Value));
    21. Console.WriteLine(matchCollection.Count);
    22. Console.WriteLine(matchCollection[0].Value);
    23. temp = columnNames[index];
    24. break;
    25. }
    26. }
    27. return temp;
    28. }

    或许还有其他方法———————-2020.5.21

    补:
    语雀内容