物流行业的宗旨就是把货物安全、准确的从一个地方中转、派送到另外一个地方,所以这个行业中,一个关键的信息就是地址。
接触这个行业多年,有一个感触,就是到目前为止没有一个公司能够在受理录单界面解决地址输入问题,为什么这么说呢?
受理员接到电话后,要发一票货物到新寨镇政府,要是受理人员知道这个地址的详细信息为:河北省唐山市乐亭县新寨镇政府,那么,她就能把这个地址很快的录入系统,问题就出来了,受理人员不可能熟记中国那么多的隶属关系吧,也不是每个受理都能知道这个地址的详细信息吧,这时要是有一个好的地址录入方法来提示,即使受理人员录入“新寨政府”也能提示“河北省唐山市乐亭县新寨镇政府”,这条信息,那么在很大程度上提高受理人员的录入效率,减轻受理人员的沟通压力,减少因为地址信息不全带来的很多问题。
引申一下,A公司在河北省唐山市,B公司在北京市朝阳区,C公司在河南省安阳市,只要客户的地址信息一确定,那么,这票货物最终的派送单位就能在受理录单后,马上就能确定出来。
例:
(1)地址信息为:河北唐山乐亭新寨政府
假如有一个好的地址匹配规则,那么就能将地址分解成【 河北省 唐山市 乐亭县 新寨镇 政府】,也就能找到这票货物的最终派送单位。
(2)还是这个信息,但是比上面少很多,信息为:河北新寨政府
如何将这条信息也能分解成功呢?近似的结果中应该包含【河北省 唐山市 乐亭县 新寨镇 政府】。
(3)假如地址信息为:063602政府
那么能否在找到的近似结果中包含【河北省 唐山市 乐亭县 新寨镇 政府】这一条呢?
(4)假如地址信息为:laotingxinzhai政府
是否也应该能否匹配到【河北省 唐山市 乐亭县 新寨镇 政府】这条信息呢?
。。。。。。。。。。。
经过几天的思考,写了一个小的测试例子,终于有办法可以解决上面的问题,但是在查询到结果后显示的顺序上还有一点不足之处,在此,我公布一下我的测试源代码,希望高人能够给与指点。
首先,建立两个文本文件来存放测试数据,
(文本文件一)1.txt,用来存储地址关键字,每行数据的关键字用“/”隔开,且每行数据的开始为城市全名,后面跟上这个城市可能用到的一些关键字,数据如下
北京市/北京/beijing
河北省/河北/hebei
宁夏回族自治区/宁夏/ningxia
新疆维吾尔自治区/新疆/xinjiang
香港特别行政区/香港/xianggang
澳门特别行政区/澳门/aomen
台湾省/台湾/taiwan
内蒙古自治区/内蒙古/neimenggu
黑龙江省/黑龙江/heilongjiang
唐山市/唐山/tangshan
乐亭县/乐亭/leting/laoting/063600
新寨镇/新寨/xinzhai/063602
朝阳区/朝阳/chaoyang/100085
(文本文件二)2.txt,用来存放每个城市对应的行政隶属关系数据,数据如下:
朝阳区/北京市朝阳区
太原市/山西省太原市
唐山市/河北省唐山市
遵化市/河北省遵化市
迁安市/河北省迁安市
乐亭县/河北省唐山市乐亭县
新寨镇/河北省唐山市乐亭县新寨镇
河北省/河北省
河南省/河南省
顺义区/北京市顺义区
代码部分:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace SearchAddress
{
public partial class Form1 : Form
{
List<string> list;
List<string> list2;
List<string> list3;
string FilePath;
string FileName1; //城市关键字文件
string FileName2; //城市详细信息文件
string FileName3; //城市详细信息文件
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//textBox1.Text = "河北新寨政府";
FilePath = System.Environment.CurrentDirectory;
FileName1 = FilePath + "//1.txt"; //城市关键字文件
FileName2 = FilePath + "//2.txt"; //城市详细信息文件
FileName3 = FilePath + "//3.txt"; //城市详细信息文件
list = new List<string>(File.ReadAllLines(FileName1, Encoding.Default));
list2 = new List<string>(File.ReadAllLines(FileName2, Encoding.Default));
list3 = new List<string>(File.ReadAllLines(FileName3, Encoding.Default));
}
AddRess GetAddRess(string Pstr)
{
AddRess myString = new AddRess();
if (Pstr.Length > 0)
{
//开始检索城市关键字信息
if (File.Exists(FileName1))
{
//开始循环搜索关键字信息
myString.OldString = Pstr.Trim();
myString = GetSubString(myString);
}
else
{
myString.substring = "";
}
}
else
{
myString.substring = "";
}
return myString;
}
AddRess GetSubString(AddRess myString)
{
myString.ResString = myString.OldString.Trim();
while (myString.ResString.Length >0)
{
myString.LastSubstring = "";
#region 开始循环
for (int len = 1; len <=myString.ResString.Length; len++)
{
string ppp = myString.ResString.Substring(0, len);
foreach (string s in list)
{
if (s.IndexOf(ppp) > -1)
{
string[] sppp = s.Split('/');
myString.LastSubstring = ppp;
myString.MaxSubstring = sppp[0].ToString();
}
}
}
if (myString.LastSubstring.Length > 0)
{
int plen = myString.LastSubstring.Length;
myString.substring += "/" + myString.MaxSubstring;
myString.ResString = myString.ResString.Substring(plen);
}
else
{
myString.ResString = myString.ResString.Substring(1);
}
#endregion
}
if (myString.substring!=null && myString.substring.Length > 0)
{
myString.substring = myString.substring.Substring(1);
}
return myString;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
AddRess ReAddRess = GetAddRess(textBox1.Text.Trim());
listBox1.Items.Clear();
if (ReAddRess.substring != null && ReAddRess.substring.Length > 0)
{
string[] pstt = ReAddRess.substring.Split('/');
int pstrlen = pstt.Length;
foreach (string s in list2)
{
string[] pop = s.Split('/');
int slen = pop.Length;
if (pop[0].IndexOf(pstt[pstrlen - 1].ToString()) > -1)
{
ReAddRess.AddressInfo = pop[1].ToString();
listBox1.Items.Add(pop[1].ToString());
}
}
listBox1.Items.Add(ReAddRess.AddressInfo + ReAddRess.ResString);
}
else
{
foreach (string ss in list3)
{
if (ss.IndexOf(textBox1.Text.Trim()) > -1)
{
listBox1.Items.Add(ss);
}
}
}
}
}
public class AddRess
{
/// <summary>
/// 原字符串
/// </summary>
public string OldString;
/// <summary>
/// 匹配字符串
/// </summary>
public string substring;
/// <summary>
/// 最后一次匹配
/// </summary>
public string LastSubstring;
/// <summary>
/// 最大匹配
/// </summary>
public string MaxSubstring;
/// <summary>
/// 剩余字符串
/// </summary>
public string ResString;
/// <summary>
/// 详细地址
/// </summary>
public string AddressInfo;
}
}
简单描述一下算法原理:
给出地址:新寨政府,算法将采用最后一次最大匹配来找相关的信息,算法实现后,在最后一次的匹配字符为“新寨镇/新寨/xinzhai/063602”,取城市全名为“新寨镇”,依据这个城市全名,找到“新寨镇/河北省唐山市乐亭县新寨镇
”这条信息,将地址信息补全,则为“河北省唐山市乐亭县新寨镇政府”,这样既可解决地址录入问题。
以上是我当时的简单的一个逻辑方法和实现实例,而且有很强的扩展性,可以在“新寨镇/新寨/xinzhai/063602”中加入其它的关键字,那么,当受理员录入地址为“063602政府”时,在匹配的结果中就会出现“河北省唐山市乐亭县新寨镇政府”这一条数据。
但是,到现在还没有一个好的显示顺序的办法,希望有这方面经历的高手给与指教,QQ:170767552/170767556,MSN:jato333@live.cn,Email:YUBODOU333@126.com。有新的解决方法,我也会及时进行更新。