【问题标题】:Create a list of objects with initialized properties from a string with infos从带有信息的字符串创建具有初始化属性的对象列表
【发布时间】:2019-02-09 12:11:32
【问题描述】:

我有一个看起来像这样的字符串:

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 个值(上面的字符串只是一个简短的示例)。

有没有更好的方法?谢谢。

【问题讨论】:

  • 字符串是json格式吗?
  • 不,它只是纯文本。你可以看上面的例子。
  • 欢迎来到 StackOverflow @asfdev991。请记住在问题本身中添加有关该问题的额外信息,以便未来的读者不必在 cmets 中寻找它;)
  • 您是否从文件中读取它?条目之间总是有这个空行吗?
  • 是的,条目之间总是有一个空行。而且字符串中还有其他文本,所以我应该忽略它。我已经更新了问题。

标签: c# string list class object


【解决方案1】:

CSV 格式似乎正是您要寻找的(因为您想在此文件中添加一些标题,实际的 CSV 星号位于第 6 行):

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);

【讨论】:

  • new User().ToList() 不会工作。另外,如果users 不需要是列表,则不需要它。
  • 上面的字符串不是 CSV 格式的。它看起来更像一个 INI 文件,但带有“:”
  • 是的,它是类似 CSV 的文件,抱歉有错别字,我已经更正了
【解决方案2】:

您可以直接创建用户列表,而不是检查每一行以将它们添加到列表中。你去:

  1. 双换行分割
  2. 换行分割
  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));
});

Try it online!

作为@Mong Zhu 的回答,删除前后的所有内容。 A这一点,这是另一个我不会尝试解决的问题。去除之前和之后的噪音,然后解析你的数据。

【讨论】:

  • 第三条记录(“chris”)与其他记录不同
  • 是的,我弄错了。
【解决方案3】:

由于它似乎总是 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;

然后简单地从 startindex 到结束取一个 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 的硬编码步长在我的解决方案中实际上很烦人

免责声明:此解决方案仅在格式不变的情况下才有效。如果行的顺序应该改变,它会返回错误的结果

【讨论】:

  • 好主意。我更喜欢RemoveSplit()
  • 加分号等同于.csv format
  • 我忘了说字符串也以另一行文本结尾(您可以在问题中看到更新的示例)。实际上,每个条目有 7 行(不是我上面说的 4 行),所以我将 "i +=4" 更改为 "i+=7" 并添加了剩余的字符串(直到 string ExString = lines[i + 6 ].Split(':').Last().Trim();) 但现在我得到“索引超出了数组的范围。”
  • @asfdev991 还有什么你忘了说的吗? ;) 呵呵好吧,有一个方法:LastIndexOf 实际上你现在应该有足够的信息来自己修复它;) 你可以用它来计算真正的 endIndex 然后取这个 SubString 的重载并只得到重要的部分
  • 是的,我已经解决了这个问题。
【解决方案4】:

对于一个强大、灵活和自记录的解决方案,它可以让您轻松添加新字段、忽略所有无关文本并满足文件格式的变化(这似乎是这样的情况,例如,没有"ID:" 中的空格仅在第 3 条记录中),我将使用 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();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 2022-11-25
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多