我有一个看起来像这样的字符串:
random text 12234
another random text
User infos:
User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID : 930712
Date : 05.11.2016
Job : job3
some random text
这堂课
class User
{
public string UserName { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
public User(string _UserName, string _ID, string _Date, string _Job)
{
UserName = _UserName
ID = _ID;
Date = _Date;
Job = _Job;
}
}
我想用该字符串中的信息创建一个用户列表。
我尝试这样做:
List<User> Users = new List<User>();
string Data = (the data above)
string[] lines = Data.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<string> UserNames = new List<string>();
List<string> IDs = new List<string>();
List<string> Dates = new List<string>();
List<string> Jobs = new List<string>();
foreach (var line in lines)
{
if (line.StartsWith("User name : "))
{
UserNames.Add(Line.Remove(0, 12));
}
if (Line.StartsWith("ID : "))
{
IDs.Add(Line.Remove(0, 5));
}
if (Line.StartsWith("Date : "))
{
Dates.Add(Line.Remove(0, 7));
}
if (Line.StartsWith("Job : "))
{
Jobs.Add(Line.Remove(0, 6));
}
}
var AllData = UserNames.Zip(IDs, (u, i) => new { UserName = u, ID = i });
foreach (var data in AllData)
{
Users.Add(new User(data.UserName, data.ID, "date", "job"));
}
但是我只能使用此代码合并两个列表。另外,我为每个用户提供了4个以上的值(上面的字符串只是一个简短的示例)。
有没有更好的方法?谢谢。
答案 0 :(得分:8)
由于似乎总是有4行信息,因此您可以在4
的步骤中进行遍历拆分数组lines
的循环。在每个步骤中,您都将用冒号:
进行拆分,并收集最后一个项目,即所需的值:
编辑:在这种情况下,我将建议您查找数据的开始。
int startIndex = Data.IndexOf("User name");
编辑2:
也以另一行文本结尾
然后您可以使用LastIndexOf查找重要信息的结尾:
int endIndex = Data.LastIndexOf("Job");
int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
endIndex += lengthOfLastLine;
然后从起始索引开始直到结束都取SubString
string [] lines = Data.Substring(startIndex, endIndex - startIndex)
.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
List<User> allUsers = new List<UserQuery.User>();
for (int i = 0; i < lines.Length; i += 4)
{
string name = lines[i].Split(':').Last().Trim();
string ID = lines[i + 1].Split(':').Last().Trim();
string Date = lines[i + 2].Split(':').Last().Trim();
string Job = lines[i + 3].Split(':').Last().Trim();
allUsers.Add(new User(name, ID, Date, Job));
}
啊,您应该Trim
隔开这些空格。
该解决方案应该是可读的。在我的解决方案中,4
的硬编码步长实际上很烦人
免责声明:此解决方案仅在格式不变的情况下有效。如果行的顺序应更改,则将返回错误结果
答案 1 :(得分:3)
您可以直接创建“用户”列表,而不是选中每一行以将它们添加到列表中。你去了:
代码:
var users = data.Split(new[] {"\n\n" }, StringSplitOptions.None).Select(lines =>
{
var line = lines.Split(new[] { "\n" }, StringSplitOptions.None);
return new User(line[0].Substring(11), line[1].Substring(4), line[2].Substring(6), line[3].Substring(5));
});
作为@Mong Zhu的答案,请删除之前和之后的所有内容。关于这一点,这是我不会尝试解决的另一个问题。在解析数据之前和之后消除噪音。
答案 2 :(得分:2)
您正在寻找CSV格式(因为您想在文件的第六行添加实际的CSV星形标题):
random text 12234
another random text
User infos:
UserName;ID;Date;Job
John;221223;23.02.2018;job1
Andrew;378292;12.08.2017;job2
Chris;930712;05.11.2016;job3
然后您可以读取该文件并进行解析:
var lines = File.ReadAllLines("pathToFile");
var dataStartIndex = lines.IndexOf("UserName;ID;Date;Job");
var Users = lines.Skip(dataStartIndex + 1).Select(s =>
{
var splittedStr = s.Split(';');
return new User(splittedStr[0], splittedStr[1], splittedStr[2], splittedStr[3]);
}).ToList();
如果您正在使用控制台条目,则只需跳过标题部分,然后让用户在不同的字符串上为每个用户输入逗号分隔的值。以相同的方式解析它:
var splittedStr = ReadLine().Split(';');
var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
Users.Add(userToAdd);
答案 3 :(得分:2)
对于健壮,灵活且具有自文档说明性的解决方案,该解决方案将使您可以轻松添加新字段,忽略所有多余的文本并满足文件格式的变化(例如,仅在第3条记录中的“ ID:”中添加空格),我将使用Regex
和一些LINQ来返回记录集合,如下所示:
using System.Text.RegularExpressions;
public class Record
{
public string Name { get; set; }
public string ID { get; set; }
public string Date { get; set; }
public string Job { get; set; }
}
public List<Record> Test()
{
string s = @"User name : John
ID : 221223
Date : 23.02.2018
Job: job1
User name : Andrew
ID : 378292
Date : 12.08.2017
Job: job2
User name : Chris
ID: 930712
Date : 05.11.2016
Job: job3
";
Regex r = new Regex(@"User\sname\s:\s(?<name>\w+).*?ID\s:\s(?<id>\w+).*?Date\s:\s(?<date>[0-9.]+).*?Job:\s(?<job>\w\w+)",RegexOptions.Singleline);
r.Matches(s);
return (from Match m in r.Matches(s)
select new Record
{
Name = m.Groups["name"].Value,
ID = m.Groups["id"].Value,
Date = m.Groups["date"].Value,
Job = m.Groups["job"].Value
}).ToList();
}