2010-01-19 7 views
4

Я знаю, что это может быть не самая результативная, но я хочу обработать некоторые журналы с помощью оператора LINQ. Вот что журнал выглядит следующим образом:Обработка журнала с помощью LINQ

RECORD DEVON 1 6748 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
RECORD JASON 1 7436 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
RECORD DEVON 2 9123 
RECORD DEVON 3 3723 
RECORD SHERRIE 1 6434 
RECORD DEVON 4 3732 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
RECORD SHERRIE 2 6434 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
RECORD SHERRIE 3 9123 
RECORD DEVON 5 3723 
bla bla bla bla bla bla 
RECORD JASON 2 9123 
RECORD DEVON 6 3723 
bla bla bla bla bla bla 
bla bla bla bla bla bla 
RECORD JASON 3 9123 

Теперь я хочу, чтобы отфильтровать все, что не начинается с записи, и группа его именем столбца (JASON, DEVON, Шерри), а затем крест присоединиться к нему по имени, это выглядит так:

DEVON JASON SHERRIE 
1/6748 1/7436 1/6434 
2/9123 2/9123 2/6434 
3/3723 3/9123 3/9123 
4/3732  
5/3723  
6/3723  

Можно ли это сделать в одном заявлении LINQ?

+0

Имеют ли бла-бла-бла столбцов соответствуют одной и той же схеме, что и соответствующие записи? – Daniel

+0

Это файл журнала, поэтому он находится в виде простого текста, поэтому нет реальной «схемы», как вы ее выразили. – skb

+0

Конечно, это возможно в одном утверждении;) - LukeH написал raytracer в одном заявлении Linq: http://blogs.msdn.com/lukeh/archive/2007/10/01/taking-linq-to-objects- к крайностям-а-полностью linqified-raytracer.aspx – jball

ответ

0

Вот что я придумал:

public static string TransformLog(string fileName) 
{ 
    const string tab = "\t"; 

    var fileLines = File.ReadAllLines(fileName); 

    var testAreas = fileLines 
     .Where(l => l.StartsWith("RECORD" + tab)) 
     .Select(l => l.Split(tab.ToCharArray()).Skip(1).Take(3).ToArray()) 
     .GroupBy(l => l[0]) 
     .Select(g => new { g.Key, Enumerator = g.GetEnumerator() }) 
     .ToList(); 

    var sb = new StringBuilder(); 

    testAreas.ForEach(ta => sb.Append(ta.Key + tab + tab)); 

    sb.AppendLine(); 

    bool cont; 

    do 
    { 
     cont = false; 

     testAreas.ForEach(ta => 
           { 
            var hasNext = ta.Enumerator.MoveNext(); 
            sb.Append((hasNext ? ta.Enumerator.Current[1] + tab + ta.Enumerator.Current[2] + tab : tab + tab)); 
            cont |= hasNext; 
           }); 

     sb.AppendLine(); 

    } while (cont); 

    return sb.ToString(); 
} 
2

Вы можете получить результаты в рядах на одном дыхании с Linq (здесь я использую метод обозначения):

string[] lines = File.ReadAllLines("input.txt"); 
var result = 
    lines.Where(line => line.Substring(0, 6) == "RECORD") 
     .Select(line => line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) 
     .GroupBy(columns => columns[1], 
        columns => columns[2] + "/" + columns[3]) 
     .Select(group => group.Key + " " + string.Join(", ", group.ToArray())); 

Выход:

DEVON 1/6748, 2/9123, 3/3723, 4/3732, 5/3723, 6/3723 
JASON 1/7436, 2/9123, 3/9123 
SHERRIE 1/6434, 2/6434, 3/9123 

Я думаю, что это трудно транспонировать строки до столбцов без стандартной функции Zip. Может быть, это достаточно хорошо для вас? Если нет, то вам, вероятно, придется сделать последний бит с помощью вспомогательного метода, который выполняет итерацию по отдельным IEnumerables.

Смежные вопросы