Andrew
Andrew

Reputation: 2335

Converting a LINQ string[] into single struct

I am currently working on a piece of code that reads in a file line by line, splits it and then stores in a data structure, i.e. I have a single line separated by spaces and I want to split into 13 elements, each corresponding to an item in the struct. I am trying to do this using LINQ with the following data structure:

public struct LogDetails
{
    public string LogDate { get; set; }
    public string LogTime { get; set; }
    public string csMethod { get; set; }
    public string csUriStem { get; set; }
    public string csUriQuery { get; set; }
    public string csUserName { get; set; }
    public string cIp { get; set; }
    public string csUserAgent { get; set; }
    public string csReferrer { get; set; }
    public string scStatus { get; set; }
    public string scSubStatus { get; set; }
    public string scBytes { get; set; }
    public string csBytes { get; set; }
}

My LINQ code for reading in the file looks as follows:

var output = inputStream.ReadLine().Split(' ').GroupBy(f => f).AsEnumerable()
                                                      .SelectMany(g => g);

When I run this it reads in the line from the file as expected and returns the 13 individual elements I would need to populate the struct. However when I try and retrieve these elements then I hit problems. Ideally, I'd like to be able to do something like the following (non working) piece of code:

IEnumerable<LogDetails> details = inputStream.ReadLine().Split(' ').GroupBy(f => f).AsEnumerable()
                                                     .SelectMany(g => new LogDetails
                                                                           {
                                                                               LogDate = g.ElementAt(0).ToString(),
                                                                               LogTime = g.ElementAt(1).ToString()
                                                                               //rest of the struct goes here
                                                                           }).ToList();

Any advice appreciated!

Andrew

Update

Thanks everyone for your responses. The completed code, for anyone who is interested is as follows:

IEnumerable<LogDetails> details = null;

details = File.ReadAllLines(pFileName)
               .Select(l => new { split = l.Split(' ') })
               .Select(s => new LogDetails
               {
                    LogDate = s.split.ElementAtOrDefault(0),
                    LogTime = s.split.ElementAtOrDefault(1),
                    csMethod = s.split.ElementAtOrDefault(2),
                    csUriStem = s.split.ElementAtOrDefault(3),
                    csUriQuery = s.split.ElementAtOrDefault(4),
                    csUserName = s.split.ElementAtOrDefault(5),
                    cIp = s.split.ElementAtOrDefault(6),
                    csUserAgent = s.split.ElementAtOrDefault(7),
                    csReferrer = s.split.ElementAtOrDefault(8),
                    scStatus = s.split.ElementAtOrDefault(9),
                    scSubStatus = s.split.ElementAtOrDefault(10),
                    scBytes = s.split.ElementAtOrDefault(11),
                    csBytes = s.split.ElementAtOrDefault(12)

                }).ToList();

Upvotes: 1

Views: 592

Answers (3)

Wasp
Wasp

Reputation: 3425

Your final solution has some redundancy, just thought to simplify it a bit:

var details = 
    from line in File.ReadAllLines(pFileName)
    let tokens = line.Split(' ')
    select new LogDetails
    {
        LogDate     = tokens[0],
        LogTime     = tokens[1],
        csMethod    = tokens[2],
        csUriStem   = tokens[3],
        csUriQuery  = tokens[4],
        csUserName  = tokens[5],
        cIp         = tokens[6],
        csUserAgent = tokens[7],
        csReferrer  = tokens[8],
        scStatus    = tokens[9],
        scSubStatus = tokens[10],
        scBytes     = tokens[11],
        csBytes     = tokens[12]
    };

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460228

I don't know why you want to use the GroupBy, i would use File.ReadLines + Enumerable.Select:

IEnumerable<LogDetails> details = File.ReadLines(filePath)
    .Select(l => new { Split = l.Split() })
    .Select(x => new LogDetails
     {
        LogDate = x.Split.ElementAt(0),
        LogTime = x.Split.ElementAtOrDefault(1),
        //rest of the struct goes here
     });

Upvotes: 4

D Stanley
D Stanley

Reputation: 152616

I'm not sue Linq is your best option here. Linq will loop through each items in the split array. You just need to initilaize an object with the items in the array.

var items = inputStream.ReadLine().Split(' ');
var details new LogDetails {
                                 LogDate = items[0],
                                 LogTime = items[1]
                                 //rest of the struct goes here
                           };

Upvotes: 2

Related Questions