检测子字符串

2 sql delphi string filtering

我有很多需要排序的数据,其中一个字段包含车辆的品牌/型号以及reg,有时用短划线( - )分隔,但有时却不是.以下是此类字符串的示例:

VehicleModel - TU69YUP

VehicleModel - TU69 YUP

VehicleModel TU69YUP

VehicleModel TU69 YUP

还有一些其他的变化,但它们是我遇到的主要变化.有没有办法让我可以可靠地查看所有数据并将车辆注册表从模型中分离出来?

数据目前包含在一个Paradox数据库中,我没有遇到任何问题.我没有数据库中包含的所有车型和名称的列表,同样,我也没有车牌列表.

该项目是用Delphi/SQL编写的,所以如果可能的话,我宁愿坚持使用其中任何一个.

Cos*_*und 5

麻烦未来

如果该字段最初是由用户以您现在看到的形式输入的,那么我们可以假设没有验证,原始程序将只存储用户输入的内容.如果是这种情况,你就无法获得100%的准确性:人类总会犯错误,无论是有意还是无意.期待这种人为错误:

  • 缺少字段(即:仅注册,没有车辆信息 - 或者相反)
  • 无意义的重复词(例如:"Ford Ford K - TU 69 YUP")
  • 缺少字母,重复的字母,额外的垃圾信件.示例:"For K-T69YUP"
  • 错误的字段顺序
  • 您甚至无法想象的其他小错误.
  • 简单的垃圾,即使是人类也不会理解.

您可能已经猜到,在将人类输入的数据直接处理到文本字段时,我有点悲观.我有一个明显的不幸来处理一个数据库,其中所有数据都是文本而且没有验证:你能猜出在无效的日期字段中输入允许免费用户输入的无意义人吗?

计划

事情并不像他们看起来那么黑暗,你可以"修复"很多东西.这里的诀窍是确保你只修复明确无误的数据,并让人类筛选其余的东西.最简单的方法是做这样的事情:

  • 查看您拥有的数据,但尚未自动修复.找出明确适用于大量记录的规则.
  • 应用明确的规则.
  • 重复,直到只剩下几条记录.这些应该手动修复,因为它们抵制了所有应用的自动方法.

实施

我强烈建议在所有测试中使用正则表达式,因为你肯定会最终实现许多不同的测试,而正则表达式可以轻松地"表达"搜索文本中的细微变化.例如,以下注册表可以解析所有4个示例并给出正确的结果:

(.*?)(\ {1,3}-\ {1,3})?(\b[A-Z]{2}\ {0,2}[0-9]{2}\ {0,3}[A-Z]{3}\b)
Run Code Online (Sandbox Code Playgroud)

如果您以前从未使用过正则表达式,那么单个表达式看起来难以理解,但事实上它非常简单.这不是一个注册问题,所以我不会详细说明.我宁愿解释一下我是如何想出这个想法的.

首先,如果文本包含车辆登记号码,那么这些号码将采用非常严格的格式:它们很容易匹配.根据您的示例,我假设所有注册号都是以下形式:

LLNNLLL
Run Code Online (Sandbox Code Playgroud)

其中"L"是一个字母,"N"是一个数字.我的正则表达式对它的解释是严格的:它只需要两个大写字母,然后是少量空格(或没有空格),接着是两个数字,接着是少量空格(或没有空格),最后紧接着是3个大写字母.正则表达式中涉及的部分是:

[A-Z]{2}\ {0,2}[0-9]{2}\ {0,3}[A-Z]{3}
Run Code Online (Sandbox Code Playgroud)

正则表达式的其余部分确保未找到嵌入到其他单词中的注册号,处理将文本分组到捕获组中并为VehicleModel创建"惰性捕获组".

如果我自己实现这个,我可能会写一个"主"函数和一些更简单的"case"函数,每个函数处理一种用户输入的变化.例:

// This function does a validation of the extracted data. For example it validates the
// Registration number, using other, more precise criteria. The parameters are VAR so the
// function may normalize the results.
function ResultsAreValid(var Make, Registration:string): Boolean;
begin
  Result := True; // Only you know what your data looks like and how it can be validated.
end;

// This is a case function that deals with a very rigid interpretation of user data
function VeryStrictInterpretation(const Text:string; out Make, Registration: string): Boolean;
var TestMake, TestReg: string;
    // regex engine ...
begin
  Result := False;
  if (your condition) then
    if ResultsAreValid(TestMake, TestReg) then
    begin
      Make := TestMake;
      Registration := TestReg;
      Result := True;
    end;    
end;

// Master function calling many different implementations that each deal with all sorts
// of variations of input. The most strict function should be first:
function MasterTest(const Text:string; out Make, Registration: string): Boolean;
begin
  Result := VeryStrictInterpretation(Text, Make, Registration);
  if not Result then Result := SomeOtherImplementation(Text, Make, Registration);      
  if not Result then Result := ThirdInterpretation(Text, Make, Registration);      
end;
Run Code Online (Sandbox Code Playgroud)

这里的想法是尝试制作多个SIMPLE程序,每个程序都以明确的方式理解一种输入; 并确保每一步都不会返回误报!最后不要忘记,一个人应该处理最后几个案例,所以不要瞄准一个解决方案.