使用Linq对日志文件进行分组

时间:2011-09-01 15:02:39

标签: linq

我有一个来自日志文件的字符串数组,格式如下:

var lines = new []
{
    "--------",
    "TimeStamp: 12:45",
    "Message: Message #1",
    "--------",
    "--------",
    "TimeStamp: 12:54",
    "Message: Message #2",
    "--------",
    "--------",
    "Message: Message #3",
    "TimeStamp: 12:55",
    "--------"
}

我想使用LINQ将每组行(由"--------"分隔)分组到一个列表中。基本上,我想要List<List<string>>或类似的,其中每个内部列表包含4个字符串 - 2个分隔符,时间戳和消息。

我应该补充一点,我希望尽可能通用,因为日志文件格式可能会改变。

可以这样做吗?

3 个答案:

答案 0 :(得分:4)

这会有用吗?

var result = Enumerable.Range(0, lines.Length / 4)
                       .Select(l => lines.Skip(l * 4).Take(4).ToList())
                       .ToList()

编辑:

这看起来有点哈哈,但我确信它可以清理

    IEnumerable<List<String>> GetLogGroups(string[] lines)
    {
        var list = new List<String>();
        foreach (var line in lines)
        {
            list.Add(line);
            if (list.Count(l => l.All(c => c == '-')) == 2)
            {
                yield return list;
                list = new List<string>();
            }
        }
    }

答案 1 :(得分:2)

你应该能够比返回List&gt;更好。如果您正在使用C#4,则可以将每组值投影到动态类型中,其中冒号前的字符串成为属性名称,值位于左侧。然后创建一个自定义迭代器,它读取行直到每个集合中出现“------”结尾,然后返回该行。在MoveNext上,您阅读下一组行。冲洗并重复直至EOF。我目前没有时间编写完整的实现,但是我在CSV上阅读并使用LINQ而不是动态对象的示例可能会让您了解自己可以做些什么。见http://www.thinqlinq.com/Post.aspx/Title/LINQ-to-CSV-using-DynamicObject。 (注意这个示例是在VB中,但同样可以在C#中完成,并进行一些修改)。

迭代器实现的另一个好处是在解析之前不必将整个文档加载到内存中。使用此版本,您一次只能加载一组块的金额。它允许您处理非常大的文件。

答案 2 :(得分:0)

假设您的结构总是

delimeter
TimeStamp
Message
delimeter

public List<List<String>> ConvertLog(String[] log)
{
    var LogSet = new List<List<String>>();
    for(i = 0; i < log.Length(); i += 4)
    {
        if (log.Length <= i+3)
        {
           var set = new List<String>() { log[i], log[i+1], log[i+2], log[i+3] };
           LogSet.Add(set);
        }
    }

}

或者在Linq

public List<List<String> ConvertLog(String[] log)
{
   return Enumerable.Range(0, lines.Length / 4)
                    .Select(l => lines.Skip(l * 4).Take(4).ToList())
                    .ToList()

}