老赵字符串抽取信息的答案
看到老赵又在得瑟地写文章出题目,为了提高下自己的脑力,花了一点时间写了以下代码:
在一开始,我甚至想到要用委托来传递分隔符分析函数进去,以提高程序的灵活性.但是后来发现这2次的分隔符分割之间,还是有耦合的,必须写在一块,所以就调整了方法.
跟别人的解决思路相比,我的方法倒是中规中矩,没有用到什么正则表达式(不想草率地看些资料就用,肯定会有bug),也没有用到让人崩溃的状态位(牛B),不过有一个优点就是把"分隔符解析"方法提取出来了,这样显得更加灵活一些.
上面的代码还差一部分功能:解析出来的token没有剥掉单引号,昨天想到一个高效的方法,可是现在又想不起来了,所以还是算了吧,留点余地出来.
Code
public class InfoFetcher
{
const string _TOKEN_GROUP_SPLITOR = "--";
const string _TOKEN_SPLITOR = "-";
/**//// <summary>
/// 从text中提取出“数据”,也就是一个List<string[]>,我们假设所有的输入都是正确的
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public List<string[]> FetchToken(string text)
{
List<string[]> tokens = new List<string[]>();
//TODO: get token group from text
var tokenGroups = SplitFrom(text, _TOKEN_GROUP_SPLITOR);
//TODO: get token from token group
foreach (var tokengroup in tokenGroups)
{
tokens.Add(SplitFrom(tokengroup, _TOKEN_SPLITOR).ToArray());
}
return tokens;
}
/**//// <summary>
/// 从字符串中获取有效的TokenGroup
/// </summary>
/// <param name="text"></param>
/// <returns>TokenGroup</returns>
private List<string> SplitFrom(string text, string splitor)
{
List<string> tokenGroup = new List<string>();
string tempText = text;
int validSplitorIndex = 0;
while (!string.IsNullOrEmpty(text))
{
validSplitorIndex = GetValidSplitorIndex(text, splitor);
if (validSplitorIndex > 0)
{//如果包含有效的分隔符,将该分隔符之前的内容获取
tokenGroup.Add(text.Remove(validSplitorIndex));
text = text.Substring(validSplitorIndex + splitor.Length);
}
else
{//已经没有
//此处还需要处理
tokenGroup.Add(text);
text = string.Empty;
}
}
return tokenGroup;
}
//获取有效分隔符的Index
private int GetValidSplitorIndex(string text, string splitor)
{
int curSplitorIndex = 0;
int validIndex = 0;
bool isValidIndexFound = false;
while (text.Contains(splitor) && (!isValidIndexFound))
{
curSplitorIndex = text.IndexOf(splitor);
if (!IsOdd(ContainCount(text.Remove(curSplitorIndex), '\'', true)))//第一个为有效Splitor
{
validIndex += curSplitorIndex;
isValidIndexFound = true;
break;
}
else
{
validIndex += (curSplitorIndex + splitor.Length);
text = text.Substring(curSplitorIndex + splitor.Length);//将第一个无效分隔符和它之前的内容干掉
}
}
return isValidIndexFound ? validIndex : 0;
}
private bool HasValidSplitor(string text, string splitor)
{
return text.Contains(splitor) && !IsOdd(ContainCount(text.Remove(text.IndexOf(splitor)), '\'', true));
}
private bool IsOdd(int p)
{
return p % 2 == 1;
}
/**//// <summary>
/// 判断一个字符串里一个字符出现的次数
/// </summary>
/// <param name="input"></param>
/// <param name="value"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
private int ContainCount(string inputString, char value, bool ignoreCase)
{
if (ignoreCase)
{
inputString = inputString.ToLower();
if (Char.IsUpper(value))
{
value = Char.ToLower(value);
}
}
int count = 0;
for (int i = 0; (i = inputString.IndexOf(value, i)) >= 0; i++)
{
count++;
}
return count;
}
}
public class InfoFetcher
{
const string _TOKEN_GROUP_SPLITOR = "--";
const string _TOKEN_SPLITOR = "-";
/**//// <summary>
/// 从text中提取出“数据”,也就是一个List<string[]>,我们假设所有的输入都是正确的
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public List<string[]> FetchToken(string text)
{
List<string[]> tokens = new List<string[]>();
//TODO: get token group from text
var tokenGroups = SplitFrom(text, _TOKEN_GROUP_SPLITOR);
//TODO: get token from token group
foreach (var tokengroup in tokenGroups)
{
tokens.Add(SplitFrom(tokengroup, _TOKEN_SPLITOR).ToArray());
}
return tokens;
}
/**//// <summary>
/// 从字符串中获取有效的TokenGroup
/// </summary>
/// <param name="text"></param>
/// <returns>TokenGroup</returns>
private List<string> SplitFrom(string text, string splitor)
{
List<string> tokenGroup = new List<string>();
string tempText = text;
int validSplitorIndex = 0;
while (!string.IsNullOrEmpty(text))
{
validSplitorIndex = GetValidSplitorIndex(text, splitor);
if (validSplitorIndex > 0)
{//如果包含有效的分隔符,将该分隔符之前的内容获取
tokenGroup.Add(text.Remove(validSplitorIndex));
text = text.Substring(validSplitorIndex + splitor.Length);
}
else
{//已经没有
//此处还需要处理
tokenGroup.Add(text);
text = string.Empty;
}
}
return tokenGroup;
}
//获取有效分隔符的Index
private int GetValidSplitorIndex(string text, string splitor)
{
int curSplitorIndex = 0;
int validIndex = 0;
bool isValidIndexFound = false;
while (text.Contains(splitor) && (!isValidIndexFound))
{
curSplitorIndex = text.IndexOf(splitor);
if (!IsOdd(ContainCount(text.Remove(curSplitorIndex), '\'', true)))//第一个为有效Splitor
{
validIndex += curSplitorIndex;
isValidIndexFound = true;
break;
}
else
{
validIndex += (curSplitorIndex + splitor.Length);
text = text.Substring(curSplitorIndex + splitor.Length);//将第一个无效分隔符和它之前的内容干掉
}
}
return isValidIndexFound ? validIndex : 0;
}
private bool HasValidSplitor(string text, string splitor)
{
return text.Contains(splitor) && !IsOdd(ContainCount(text.Remove(text.IndexOf(splitor)), '\'', true));
}
private bool IsOdd(int p)
{
return p % 2 == 1;
}
/**//// <summary>
/// 判断一个字符串里一个字符出现的次数
/// </summary>
/// <param name="input"></param>
/// <param name="value"></param>
/// <param name="ignoreCase"></param>
/// <returns></returns>
private int ContainCount(string inputString, char value, bool ignoreCase)
{
if (ignoreCase)
{
inputString = inputString.ToLower();
if (Char.IsUpper(value))
{
value = Char.ToLower(value);
}
}
int count = 0;
for (int i = 0; (i = inputString.IndexOf(value, i)) >= 0; i++)
{
count++;
}
return count;
}
}
在一开始,我甚至想到要用委托来传递分隔符分析函数进去,以提高程序的灵活性.但是后来发现这2次的分隔符分割之间,还是有耦合的,必须写在一块,所以就调整了方法.
跟别人的解决思路相比,我的方法倒是中规中矩,没有用到什么正则表达式(不想草率地看些资料就用,肯定会有bug),也没有用到让人崩溃的状态位(牛B),不过有一个优点就是把"分隔符解析"方法提取出来了,这样显得更加灵活一些.
上面的代码还差一部分功能:解析出来的token没有剥掉单引号,昨天想到一个高效的方法,可是现在又想不起来了,所以还是算了吧,留点余地出来.