最近在进行语音项目,涉及到了时间提取,城市提取等,之前也学过python,对于实体识别这方面也有涉及,于是把python代码方面转化为c#代码,方便自己理解。
时间提取是比较复杂的一项提取,因为涉及到了中文日期转数字,年份转数字,时间格式化为字符串,检查时间合法性等等。
起初我的想法是,不是只有把传进来的中文直接转为数字即可吗,例如十–>10,但仔细想了一下,发现不对,因为当转化到十位数,百位数,千位数的时候,直接转化是错误的,例如一千二百–>1/1000/2/100
,完全脱离了我们提取的数字。因此不能直接转化。
首先了解一下,我们传入的字符串的正则表达式:
([0-9零一二两三四五六七八九十]+年)?([0-9一二两三四五六七八九十]+月)?([0-9一二两三四五六七八九十]+[号日])?([上中下午晚早]+)?([0-9零一二两三四五六七八九十百]+[点:\.时])?([0-9零一二两三四五六七八九十百]+分?)?([0-9零一二三四五六七八九十百]+秒)?
可以看到,匹配格式为xxxx年xx月xx日xx日这种,因此处理时要注意这些。
接下来开始处理:
定义普通中文数字和十百千万的字典。
private readonly static Dictionary<char, int> UTIL_CN_UNIT = new Dictionary<char, int>
{
{
'十', 10 }, {
'百', 100 }, {
'千', 1000 }, {
'万', 10000 }
};
private readonly static Dictionary<char, int> UTIL_CN_NUM = new Dictionary<char, int>
{
{
'零', 0 },{
'一', 1 }, {
'二', 2 },{
'两', 2 }, {
'三', 3 },
{
'四', 4 },{
'五', 5 }, {
'六', 6 },{
'七', 7 }, {
'八', 8 },
{
'九', 9 },{
'0', 0 }, {
'1', 1 }, {
'2', 2 }, {
'3', 3 }, {
'4', 4 },
{
'5', 5 }, {
'6', 6 },{
'7', 7 }, {
'8', 8 }, {
'9', 9 }
};
c#的Regex类是处理正则表达式的。
public static int Cn2Dig(string src)
{
if (src == "") return -1;
Match m = Regex.Match(src, @"\d+");
if (m != Match.Empty)
{
return Convert.ToInt32(m.Groups[0].Value);
}
int rsl = 0;
int unit = 1;
for (int i = src.Length - 2; i >= 0; i--)//减二是因为最后一个为号,日,时分这种
{
if (UTIL_CN_UNIT.ContainsKey(src[i]))//十百千这种数字
{
unit = UTIL_CN_UNIT[src[i]];
}
else if (UTIL_CN_NUM.ContainsKey(src[i]))//0~9这种数字
{
int num = UTIL_CN_NUM[src[i]];
rsl += num * unit;
}
else
{
return -1;
}
}
if (rsl
因篇幅问题不能全部显示,请点此查看更多更全内容