我有一个输入字符串,如下所示:
4 Bob 32 Joe 64 Sue 123 Bill 42
其中4表示要遵循的字符串整数对的数量。我目前的处理方式如下所示:
var strings = input.Split(' ');
int count = Int32.Parse(strings[0]);
for ( int i = 0; i < count; i++ )
{
string name = strings[count*2 + 1];
int number = Int32.Parse(strings[count*2 + 1]);
ProcessPerson(name, number);
}
这感觉非常麻烦。 C#中是否有一些库可以包装字符串并为我提供“readInt”和“readString”等服务。我最终会喜欢这样的东西:
int count = input.ReadInt();
for(int i = 0; i<count; i++)
{
ProcessPerson(input.ReadString(), input.ReadInt());
}
在这种情况下看起来并没有那么多改进,但我的实际对象模型有点复杂。我知道其他语言有这样的设施,但我不记得任何.net库只是从字符串的前面读取。
答案 0 :(得分:1)
这可能会好一点:
var strings = input.Split(' ');
for ( int i = 2; i < strings.length; i + 2 )
{
ProcessPerson(strings[i - 1], Int32.Parse(strings[i]));
}
答案 1 :(得分:1)
我建议你为此目的使用正则表达式。这是一个例子:
string input = "4 Bob 32 Joe 64 Sue 123 Bill";
var matches = Regex.Matches(input, @"(?:(\d+) ([a-zA-Z]+))+");
for (int i = 0; i < matches.Count; i++)
{
Console.WriteLine("Number: {0} \t Person: {1}", matches[i].Groups[1], matches[i].Groups[2]);
}
将打印:
Number: 4 Person: Bob Number: 32 Person: Joe Number: 64 Person: Sue Number: 123 Person: Bill
使用正则表达式时,您需要知道的是如何表达您想要匹配的模式。在这种情况下,您要匹配:
[Number][Space][Letters]
一次或多次,对吗?这正是它的含义:
(\d+) ([a-zA-Z]+)
编辑1:
在这一刻,我真的不知道你是否想要将每个人之前或之后的数字联系到每个人,但你所要做的就是交换上面的模式,所以它将成为:
(?:([a-zA-Z]+) (\d+))+
编辑2:
如果要跳过第一个数字,可以使用此模式:
\d+ (?:([a-zA-Z]+) (\d+))+
所以你要匹配一个数字(\d+
),然后是一个空格(),然后匹配你之前匹配的那个(
Name Number Name Number ...
)
答案 2 :(得分:1)
您可以自己轻松编写这样的“图书馆”:
class Parser
{
private readonly Queue<string> m_parts;
public Parser(string s)
{
m_parts = new Queue<string>(s.Split(' '));
}
public string ReadString()
{
return m_parts.Dequeue();
}
public int ReadInt32()
{
return int.Parse(ReadString());
}
}
如果字符串可能很大,或者您正在从流中读取它,则必须自己进行拆分:
class StreamParser
{
private readonly TextReader m_reader;
public StreamParser(string s)
: this(new StringReader(s))
{}
public StreamParser(TextReader reader)
{
m_reader = reader;
}
public string ReadString()
{
var result = new StringBuilder();
int c = m_reader.Read();
while (c != -1 && (char)c != ' ')
{
result.Append((char)c);
c = m_reader.Read();
}
if (result.Length > 0)
return result.ToString();
return null;
}
public int ReadInt32()
{
return int.Parse(ReadString());
}
}
答案 3 :(得分:1)
尝试从队列中读取,它可能更清洁一点:
var s = "4 Bob 32 Joe 64 Sue 123 Bill 42";
var queue = new Queue(s.Split(' '));
var count = Convert.ToInt32(queue.Dequeue());
while (queue.Count != 0)
{
var name = queue.Dequeue();
var number = Convert.ToInt32(queue.Dequeue());
ProcessPerson(name, number);
}
如果您向Queue添加扩展方法,则可以进一步简化(未经测试):
public static class QueueExtensions {
public static int DequeueInt(this Queue<string> queue) {
return Convert.ToInt32(queue.Dequeue());
}
}
ProcessPerson(queue.DequeueInt(), queue.Dequeue());
您应该在其中添加各种防护,以避免尝试将空队列出列并使转换无效。