0

I have two lists that hold logging data (the lists hold strings).
An example list1 would look the following way (each entry is a string):
11:03:01:003 INFO some event has occurred 11:03:31:004 DEBUG another event has occurred 11:04:01:015 INFO third event has occurred
An example list2 would look the following way:
11:03:16:003 INFO fourth event has occurred 11:03:32:025 DEBUG fifth event has occurred 11:03:54:023 INFO sixth event has occurred

My goal is to have a list3 that will look the following way:
11:03:01:003 INFO some event has occurred 11:03:16:003 INFO fourth event has occurred 11:03:31:004 DEBUG another event has occurred 11:03:32:025 DEBUG fifth event has occurred 11:03:54:023 INFO sixth event has occurred 11:04:01:015 INFO third event has occurred

I have been thinking of an efficient way of solving this (as the log files can get quite heavy) but was not really able to figure it out.

Edit: The Lists come from ".txt" files and are split by a certain characteristic so I can end up with having to merge even more than two lists but the first step I had to do was generate those Lists which I was able to accomplish.

mykhailo
  • 117
  • 2
  • 14

2 Answers2

0

You could use LINQ for this, by getting first the time and then ordering:

var result = list
    .Select(x => 
    { 
        return new { Log = x, Time = TimeSpan.Parse(x.Split(' ')[0]) }; 
    })
    .OrderBy(x => x.Time)
    .Select(x => x.Log) // only if you don't care anymore about the time
    .ToArray();

For example, something like this:

var list = new List<string>();
list.Add("11:03:01:003 INFO some event has occurred");
list.Add("11:03:31:004 DEBUG another event has occurred");
list.Add("11:04:01:015 INFO third event has occurred");

var list2 = new List<string>();
list2.Add("11:03:16:003 INFO fourth event has occurred");
list2.Add("11:03:32:025 DEBUG fifth event has occurred");
list2.Add("11:03:54:023 INFO sixth event has occurred");

var result = list
    // Merge both lists
    .Union(list2)
    .Select(x => 
    { 
        return new { Log = x, Time = TimeSpan.Parse(x.Split(' ')[0]) }; 
    })
    .OrderBy(x => x.Time)
    .ToArray();

foreach (var log in result)
{
    Console.WriteLine(log.Time + " => " + log.Log);
}

Which prints:

11.03:01:03 => 11:03:01:003 INFO some event has occurred
11.03:16:03 => 11:03:16:003 INFO fourth event has occurred
11.03:31:04 => 11:03:31:004 DEBUG another event has occurred
11.03:32:25 => 11:03:32:025 DEBUG fifth event has occurred
11.03:54:23 => 11:03:54:023 INFO sixth event has occurred
11.04:01:15 => 11:04:01:015 INFO third event has occurred

As you can see in this fiddle.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • thank you, that helped a lot. I have not worked with linq much so building all these Select and Where statements is kind of new to me. I also have a follow-up question. When I am parsing the txt log file to get this log entries, corresponding timestamp can have data that is multiple lines, for example, `11.04:01:15 INFO info that takes 35 lines in txt file` and I am not sure how to use linq to store that in the list. – mykhailo Nov 09 '18 at 20:04
  • @mykhailo First of all, that's a different question, and should be a new one if this is solved. Secondly, are those *really* 35 lines, with `\r\n` (enter character in Windows)? Open the file with Notepad++ or some program that can actually tell you the number of lines. – Camilo Terevinto Nov 09 '18 at 23:31
  • sorry, I was going to post another question but felt like it'd be more efficient to follow-up. Correct, I have checked and those are really new lines so I need to parse them accordingly and store the whole event in one entry. – mykhailo Nov 11 '18 at 18:25
0

If each list is ordered the most efficient way is to do a merge (O(m + n) where m and n are the lengths of the lists), just like in merge sort algorithm:

var result = new List<string>(m+n);
int i = 0, j = 0;
while (i < l1.Count && j < l2.Count) {
    if (l1[i] < l2[j]) { // Of course you have to change this part, the idea is to compare both items
        result.Add(l1[i++]);
    } else {
        result.Add(l2[j++]);
    }
}

while(i < l1.Count) { result.Add(l1[i++]); }
while(j < l2.Count) { result.Add(l2[j++]); }
dcg
  • 4,187
  • 1
  • 18
  • 32