Создайте список объектов с инициализированными свойствами из строки с информацией - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть строка, которая выглядит так:

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 значений для каждого пользователя (приведенная выше строка была лишь кратким примером).

Есть ли лучший метод? Спасибо.

Ответы [ 4 ]

0 голосов
/ 04 сентября 2018

Для надежного, гибкого и самодокументируемого решения, которое позволит вам легко добавлять новые поля, игнорировать весь посторонний текст, а также учитывать изменения в формате вашего файла (например, это не так, например, пробел в «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();
    }
0 голосов
/ 04 сентября 2018

Вместо проверки каждой строки для добавления каждой из них в список, вы можете создать свой список пользователей напрямую. Вот и вы:

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

Попробуйте онлайн!

Как ответ @Mong Zhu, удалите все до и после. С этой точки зрения, это еще один вопрос, который я не буду пытаться решить. Удалите шум до и после, затем проанализируйте ваши данные.

0 голосов
/ 04 сентября 2018

Так как кажется, что это всегда 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 на самом деле раздражает в моем решении

Отказ от ответственности: это решение работает только до тех пор, пока формат не изменится. Если порядок строк изменится, он вернет ложные результаты

0 голосов
/ 04 сентября 2018

Формат 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...