Create a list of objects with initialized properties from a string with infos

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
9
down vote

favorite
2












I have a string that looks like that:



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


And this class:



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;




And I want to create a List of Users with informations from that string.



I have tried doing that:



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



But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .



Is there a better method? Thanks.







share|improve this question









New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • is the string is in withing json format?
    – styx
    Sep 4 at 12:44










  • No, it is just plain text. You can see the example above.
    – asfdev991
    Sep 4 at 12:45






  • 1




    Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
    – Ian
    Sep 4 at 12:53










  • do you read it from a file? is there always this empty line between the entries?
    – Mong Zhu
    Sep 4 at 13:03










  • Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
    – asfdev991
    Sep 4 at 13:07














up vote
9
down vote

favorite
2












I have a string that looks like that:



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


And this class:



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;




And I want to create a List of Users with informations from that string.



I have tried doing that:



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



But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .



Is there a better method? Thanks.







share|improve this question









New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • is the string is in withing json format?
    – styx
    Sep 4 at 12:44










  • No, it is just plain text. You can see the example above.
    – asfdev991
    Sep 4 at 12:45






  • 1




    Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
    – Ian
    Sep 4 at 12:53










  • do you read it from a file? is there always this empty line between the entries?
    – Mong Zhu
    Sep 4 at 13:03










  • Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
    – asfdev991
    Sep 4 at 13:07












up vote
9
down vote

favorite
2









up vote
9
down vote

favorite
2






2





I have a string that looks like that:



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


And this class:



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;




And I want to create a List of Users with informations from that string.



I have tried doing that:



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



But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .



Is there a better method? Thanks.







share|improve this question









New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










I have a string that looks like that:



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


And this class:



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;




And I want to create a List of Users with informations from that string.



I have tried doing that:



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



But I can only combine two lists using this code. Also, I have more than 4 values for each user (the string above was just a short example) .



Is there a better method? Thanks.









share|improve this question









New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Sep 4 at 13:38





















New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Sep 4 at 12:42









asfdev991

484




484




New contributor




asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






asfdev991 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











  • is the string is in withing json format?
    – styx
    Sep 4 at 12:44










  • No, it is just plain text. You can see the example above.
    – asfdev991
    Sep 4 at 12:45






  • 1




    Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
    – Ian
    Sep 4 at 12:53










  • do you read it from a file? is there always this empty line between the entries?
    – Mong Zhu
    Sep 4 at 13:03










  • Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
    – asfdev991
    Sep 4 at 13:07
















  • is the string is in withing json format?
    – styx
    Sep 4 at 12:44










  • No, it is just plain text. You can see the example above.
    – asfdev991
    Sep 4 at 12:45






  • 1




    Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
    – Ian
    Sep 4 at 12:53










  • do you read it from a file? is there always this empty line between the entries?
    – Mong Zhu
    Sep 4 at 13:03










  • Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
    – asfdev991
    Sep 4 at 13:07















is the string is in withing json format?
– styx
Sep 4 at 12:44




is the string is in withing json format?
– styx
Sep 4 at 12:44












No, it is just plain text. You can see the example above.
– asfdev991
Sep 4 at 12:45




No, it is just plain text. You can see the example above.
– asfdev991
Sep 4 at 12:45




1




1




Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
– Ian
Sep 4 at 12:53




Welcome to StackOverflow @asfdev991. Please remember to add extra information about the question into the question itself so that future readers don't have to trawl the comments to find it ;)
– Ian
Sep 4 at 12:53












do you read it from a file? is there always this empty line between the entries?
– Mong Zhu
Sep 4 at 13:03




do you read it from a file? is there always this empty line between the entries?
– Mong Zhu
Sep 4 at 13:03












Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
– asfdev991
Sep 4 at 13:07




Yes, there is always a empty line between the entries. And the string also has other text in it, so I should ignore it. I have updated the question.
– asfdev991
Sep 4 at 13:07












4 Answers
4






active

oldest

votes

















up vote
8
down vote



accepted










Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:



EDIT: In this case I would suggets to look for the START of the data.



int startIndex = Data.IndexOf("User name");


EDIT 2:




also ends with another line of text




then you can use LastIndexOf to find the end of the important information:



int endIndex = Data.LastIndexOf("Job");
int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
endIndex += lengthOfLastLine;


and then simply take a SubString from the startindex on until the end



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



Ahhh, and you should Trim the spaces away.
This solution should be readable. The hard coded step size of 4 is actually annoying in my solution



Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results






share|improve this answer


















  • 1




    Great idea. I prefer Remove to Split() though.
    – aloisdg
    Sep 4 at 12:57






  • 1




    With semicolon it is the same as .csv format
    – Fabjan
    Sep 4 at 13:00











  • I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
    – asfdev991
    Sep 4 at 13:30











  • @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
    – Mong Zhu
    Sep 4 at 13:40







  • 1




    Yes, I have fixed the issue.
    – asfdev991
    Sep 4 at 14:02

















up vote
3
down vote













Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:



  1. Split by double new line

  2. Split by new line

  3. Build each User

Code:



var users = data.Split(new "nn" , 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!



As @Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.






share|improve this answer






















  • The 3rd record (for "chris") is different from the rest
    – Tian van Heerden
    Sep 4 at 13:26










  • @TianvanHeerden updated :)
    – aloisdg
    Sep 4 at 13:38










  • Yes, I made a mistake.
    – asfdev991
    Sep 4 at 13:39

















up vote
2
down vote













For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:



 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(@"Usersnames:s(?<name>w+).*?IDs:s(?<id>w+).*?Dates:s(?<date>[0-9.]+).*?Job:s(?<job>ww+)",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();






share|improve this answer



























    up vote
    2
    down vote













    The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):



    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


    And then you could read this file and parse it:



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


    If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:



    var splittedStr = ReadLine().Split(';');
    var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
    Users.Add(userToAdd);





    share|improve this answer






















    • new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
      – aloisdg
      Sep 4 at 13:40










    • The string above is not in the CSV format. It looks more like a INI file, but with a ":"
      – asfdev991
      Sep 4 at 13:44










    • Yup, it's CSV-like file, sorry for typos, I've corrected them
      – Fabjan
      Sep 4 at 13:53










    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );






    asfdev991 is a new contributor. Be nice, and check out our Code of Conduct.









     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52166644%2fcreate-a-list-of-objects-with-initialized-properties-from-a-string-with-infos%23new-answer', 'question_page');

    );

    Post as a guest






























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    8
    down vote



    accepted










    Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:



    EDIT: In this case I would suggets to look for the START of the data.



    int startIndex = Data.IndexOf("User name");


    EDIT 2:




    also ends with another line of text




    then you can use LastIndexOf to find the end of the important information:



    int endIndex = Data.LastIndexOf("Job");
    int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
    endIndex += lengthOfLastLine;


    and then simply take a SubString from the startindex on until the end



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



    Ahhh, and you should Trim the spaces away.
    This solution should be readable. The hard coded step size of 4 is actually annoying in my solution



    Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results






    share|improve this answer


















    • 1




      Great idea. I prefer Remove to Split() though.
      – aloisdg
      Sep 4 at 12:57






    • 1




      With semicolon it is the same as .csv format
      – Fabjan
      Sep 4 at 13:00











    • I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
      – asfdev991
      Sep 4 at 13:30











    • @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
      – Mong Zhu
      Sep 4 at 13:40







    • 1




      Yes, I have fixed the issue.
      – asfdev991
      Sep 4 at 14:02














    up vote
    8
    down vote



    accepted










    Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:



    EDIT: In this case I would suggets to look for the START of the data.



    int startIndex = Data.IndexOf("User name");


    EDIT 2:




    also ends with another line of text




    then you can use LastIndexOf to find the end of the important information:



    int endIndex = Data.LastIndexOf("Job");
    int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
    endIndex += lengthOfLastLine;


    and then simply take a SubString from the startindex on until the end



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



    Ahhh, and you should Trim the spaces away.
    This solution should be readable. The hard coded step size of 4 is actually annoying in my solution



    Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results






    share|improve this answer


















    • 1




      Great idea. I prefer Remove to Split() though.
      – aloisdg
      Sep 4 at 12:57






    • 1




      With semicolon it is the same as .csv format
      – Fabjan
      Sep 4 at 13:00











    • I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
      – asfdev991
      Sep 4 at 13:30











    • @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
      – Mong Zhu
      Sep 4 at 13:40







    • 1




      Yes, I have fixed the issue.
      – asfdev991
      Sep 4 at 14:02












    up vote
    8
    down vote



    accepted







    up vote
    8
    down vote



    accepted






    Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:



    EDIT: In this case I would suggets to look for the START of the data.



    int startIndex = Data.IndexOf("User name");


    EDIT 2:




    also ends with another line of text




    then you can use LastIndexOf to find the end of the important information:



    int endIndex = Data.LastIndexOf("Job");
    int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
    endIndex += lengthOfLastLine;


    and then simply take a SubString from the startindex on until the end



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



    Ahhh, and you should Trim the spaces away.
    This solution should be readable. The hard coded step size of 4 is actually annoying in my solution



    Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results






    share|improve this answer














    Since it seems to be always 4 lines of information you could go in steps of 4 with a loop through the splitted array lines. At each step you would split by colon : and collect the last item, which is the desired value:



    EDIT: In this case I would suggets to look for the START of the data.



    int startIndex = Data.IndexOf("User name");


    EDIT 2:




    also ends with another line of text




    then you can use LastIndexOf to find the end of the important information:



    int endIndex = Data.LastIndexOf("Job");
    int lengthOfLastLine = Data.Substring(endIndex).IndexOf(Environment.NewLine);
    endIndex += lengthOfLastLine;


    and then simply take a SubString from the startindex on until the end



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



    Ahhh, and you should Trim the spaces away.
    This solution should be readable. The hard coded step size of 4 is actually annoying in my solution



    Disclaimer: This solution works only as long as the format does not change. If the order of the lines should change, it will return false results







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 5 at 7:19

























    answered Sep 4 at 12:55









    Mong Zhu

    14.6k52247




    14.6k52247







    • 1




      Great idea. I prefer Remove to Split() though.
      – aloisdg
      Sep 4 at 12:57






    • 1




      With semicolon it is the same as .csv format
      – Fabjan
      Sep 4 at 13:00











    • I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
      – asfdev991
      Sep 4 at 13:30











    • @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
      – Mong Zhu
      Sep 4 at 13:40







    • 1




      Yes, I have fixed the issue.
      – asfdev991
      Sep 4 at 14:02












    • 1




      Great idea. I prefer Remove to Split() though.
      – aloisdg
      Sep 4 at 12:57






    • 1




      With semicolon it is the same as .csv format
      – Fabjan
      Sep 4 at 13:00











    • I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
      – asfdev991
      Sep 4 at 13:30











    • @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
      – Mong Zhu
      Sep 4 at 13:40







    • 1




      Yes, I have fixed the issue.
      – asfdev991
      Sep 4 at 14:02







    1




    1




    Great idea. I prefer Remove to Split() though.
    – aloisdg
    Sep 4 at 12:57




    Great idea. I prefer Remove to Split() though.
    – aloisdg
    Sep 4 at 12:57




    1




    1




    With semicolon it is the same as .csv format
    – Fabjan
    Sep 4 at 13:00





    With semicolon it is the same as .csv format
    – Fabjan
    Sep 4 at 13:00













    I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
    – asfdev991
    Sep 4 at 13:30





    I forgot to say that the string also ends with another line of text (you can see the updated example in the question). In reality, each entry has 7 lines (not 4 as I said above), so I have changed "i +=4" to "i+=7" and I have added the remaining string (until string ExString = lines[i + 6].Split(':').Last().Trim();) but now I get "Index was outside the bounds of the array."
    – asfdev991
    Sep 4 at 13:30













    @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
    – Mong Zhu
    Sep 4 at 13:40





    @asfdev991 something else you forgot to say ? ;) hehe ok, there is a method: LastIndexOf actually you should have enough information to fix it on your own now ;) You can use it to calculate the real endIndex then take this overload of SubString and get only the important part
    – Mong Zhu
    Sep 4 at 13:40





    1




    1




    Yes, I have fixed the issue.
    – asfdev991
    Sep 4 at 14:02




    Yes, I have fixed the issue.
    – asfdev991
    Sep 4 at 14:02












    up vote
    3
    down vote













    Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:



    1. Split by double new line

    2. Split by new line

    3. Build each User

    Code:



    var users = data.Split(new "nn" , 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!



    As @Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.






    share|improve this answer






















    • The 3rd record (for "chris") is different from the rest
      – Tian van Heerden
      Sep 4 at 13:26










    • @TianvanHeerden updated :)
      – aloisdg
      Sep 4 at 13:38










    • Yes, I made a mistake.
      – asfdev991
      Sep 4 at 13:39














    up vote
    3
    down vote













    Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:



    1. Split by double new line

    2. Split by new line

    3. Build each User

    Code:



    var users = data.Split(new "nn" , 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!



    As @Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.






    share|improve this answer






















    • The 3rd record (for "chris") is different from the rest
      – Tian van Heerden
      Sep 4 at 13:26










    • @TianvanHeerden updated :)
      – aloisdg
      Sep 4 at 13:38










    • Yes, I made a mistake.
      – asfdev991
      Sep 4 at 13:39












    up vote
    3
    down vote










    up vote
    3
    down vote









    Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:



    1. Split by double new line

    2. Split by new line

    3. Build each User

    Code:



    var users = data.Split(new "nn" , 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!



    As @Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.






    share|improve this answer














    Instead of checking each line to add each of them to a a list, you can create your list of User directly. There you go:



    1. Split by double new line

    2. Split by new line

    3. Build each User

    Code:



    var users = data.Split(new "nn" , 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!



    As @Mong Zhu answer, remove everything before and after. A this point, this is another question I wont try to solve. Remove the noise before and after then parse your data.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Sep 4 at 13:43

























    answered Sep 4 at 12:51









    aloisdg

    8,12523649




    8,12523649











    • The 3rd record (for "chris") is different from the rest
      – Tian van Heerden
      Sep 4 at 13:26










    • @TianvanHeerden updated :)
      – aloisdg
      Sep 4 at 13:38










    • Yes, I made a mistake.
      – asfdev991
      Sep 4 at 13:39
















    • The 3rd record (for "chris") is different from the rest
      – Tian van Heerden
      Sep 4 at 13:26










    • @TianvanHeerden updated :)
      – aloisdg
      Sep 4 at 13:38










    • Yes, I made a mistake.
      – asfdev991
      Sep 4 at 13:39















    The 3rd record (for "chris") is different from the rest
    – Tian van Heerden
    Sep 4 at 13:26




    The 3rd record (for "chris") is different from the rest
    – Tian van Heerden
    Sep 4 at 13:26












    @TianvanHeerden updated :)
    – aloisdg
    Sep 4 at 13:38




    @TianvanHeerden updated :)
    – aloisdg
    Sep 4 at 13:38












    Yes, I made a mistake.
    – asfdev991
    Sep 4 at 13:39




    Yes, I made a mistake.
    – asfdev991
    Sep 4 at 13:39










    up vote
    2
    down vote













    For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:



     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(@"Usersnames:s(?<name>w+).*?IDs:s(?<id>w+).*?Dates:s(?<date>[0-9.]+).*?Job:s(?<job>ww+)",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();






    share|improve this answer
























      up vote
      2
      down vote













      For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:



       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(@"Usersnames:s(?<name>w+).*?IDs:s(?<id>w+).*?Dates:s(?<date>[0-9.]+).*?Job:s(?<job>ww+)",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();






      share|improve this answer






















        up vote
        2
        down vote










        up vote
        2
        down vote









        For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:



         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(@"Usersnames:s(?<name>w+).*?IDs:s(?<id>w+).*?Dates:s(?<date>[0-9.]+).*?Job:s(?<job>ww+)",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();






        share|improve this answer












        For a robust, flexible and self-documenting solution that will allow you to easily add new fields, ignore all the extraneous text and also cater for variations in your file format (this seems to be the case with, for example, no space in "ID:" only in the 3rd record), I would use a Regex and some LINQ to return a collection of records as follows:



         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(@"Usersnames:s(?<name>w+).*?IDs:s(?<id>w+).*?Dates:s(?<date>[0-9.]+).*?Job:s(?<job>ww+)",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();







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Sep 4 at 13:24









        Tian van Heerden

        54926




        54926




















            up vote
            2
            down vote













            The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):



            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


            And then you could read this file and parse it:



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


            If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:



            var splittedStr = ReadLine().Split(';');
            var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
            Users.Add(userToAdd);





            share|improve this answer






















            • new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
              – aloisdg
              Sep 4 at 13:40










            • The string above is not in the CSV format. It looks more like a INI file, but with a ":"
              – asfdev991
              Sep 4 at 13:44










            • Yup, it's CSV-like file, sorry for typos, I've corrected them
              – Fabjan
              Sep 4 at 13:53














            up vote
            2
            down vote













            The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):



            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


            And then you could read this file and parse it:



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


            If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:



            var splittedStr = ReadLine().Split(';');
            var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
            Users.Add(userToAdd);





            share|improve this answer






















            • new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
              – aloisdg
              Sep 4 at 13:40










            • The string above is not in the CSV format. It looks more like a INI file, but with a ":"
              – asfdev991
              Sep 4 at 13:44










            • Yup, it's CSV-like file, sorry for typos, I've corrected them
              – Fabjan
              Sep 4 at 13:53












            up vote
            2
            down vote










            up vote
            2
            down vote









            The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):



            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


            And then you could read this file and parse it:



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


            If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:



            var splittedStr = ReadLine().Split(';');
            var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
            Users.Add(userToAdd);





            share|improve this answer














            The CSV format seems to be what you're looking for (since you want to add some header to this file the actual CSV stars on 6th line):



            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


            And then you could read this file and parse it:



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


            If you're working with console entry just skip the header part and let user enter comma separated values for each user on a different string. Parse it in a same way:



            var splittedStr = ReadLine().Split(';');
            var userToAdd = new User(splittedStr[0], splittedStr[1], splittedStr[2] , splittedStr[3]);
            Users.Add(userToAdd);






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Sep 4 at 13:49

























            answered Sep 4 at 12:50









            Fabjan

            8,59521438




            8,59521438











            • new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
              – aloisdg
              Sep 4 at 13:40










            • The string above is not in the CSV format. It looks more like a INI file, but with a ":"
              – asfdev991
              Sep 4 at 13:44










            • Yup, it's CSV-like file, sorry for typos, I've corrected them
              – Fabjan
              Sep 4 at 13:53
















            • new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
              – aloisdg
              Sep 4 at 13:40










            • The string above is not in the CSV format. It looks more like a INI file, but with a ":"
              – asfdev991
              Sep 4 at 13:44










            • Yup, it's CSV-like file, sorry for typos, I've corrected them
              – Fabjan
              Sep 4 at 13:53















            new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
            – aloisdg
            Sep 4 at 13:40




            new User().ToList() wont work. Also, you dont need it if users doesnt need to be a list.
            – aloisdg
            Sep 4 at 13:40












            The string above is not in the CSV format. It looks more like a INI file, but with a ":"
            – asfdev991
            Sep 4 at 13:44




            The string above is not in the CSV format. It looks more like a INI file, but with a ":"
            – asfdev991
            Sep 4 at 13:44












            Yup, it's CSV-like file, sorry for typos, I've corrected them
            – Fabjan
            Sep 4 at 13:53




            Yup, it's CSV-like file, sorry for typos, I've corrected them
            – Fabjan
            Sep 4 at 13:53










            asfdev991 is a new contributor. Be nice, and check out our Code of Conduct.









             

            draft saved


            draft discarded


















            asfdev991 is a new contributor. Be nice, and check out our Code of Conduct.












            asfdev991 is a new contributor. Be nice, and check out our Code of Conduct.











            asfdev991 is a new contributor. Be nice, and check out our Code of Conduct.













             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52166644%2fcreate-a-list-of-objects-with-initialized-properties-from-a-string-with-infos%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            List of Gilmore Girls characters

            Confectionery