2017-01-31 2 views
1

У меня есть некоторые проблемы с linq to txt file. Txt файл имеет следующую специфическую структуру:C# Lambda to txt file

================ 09.01.2017 [8:51:11] created by VBScript ================ 

    ....some text 

============================= END ============================= 

================ 16.01.2017 [9:49:09] created by VBScript ================ 

    ....some text 

============================= END ============================= 

================ 18.01.2017 [8:43:50] created by VBScript ================ 

    ....some text 

============================= END ============================= 

etc 

Поэтому я хочу, чтобы выбрать все строки из этого файла, который начинается и заканчивается с «=» и выберите их индексы (позиции) в нем.

Первый шаг: я открыл и convertered его в список (потому что легче работать со списком)

string filekvitErrorGroupsResource = Utils.ReadTextResource(resourceName, Assembly.GetExecutingAssembly()); 
string[] stringSeparators = {"\r\n"}; 
string[] lines = filekvitErrorGroupsResource.Split(stringSeparators, StringSplitOptions.None); 
return new List<string>(lines); 

Второй шаг: Я пытался сделать простой запрос лямбда в список по условию:

var myQuery = lines.Where(l => l.StartsWith("=") && l.EndsWith("=")) 
        .Select(l => new {idx = lines.IndexOf(l), body = l}); 

ПРОБЛЕМА: в результате я ожидаю получить список строк с уникальными индексами (IDX), но вместо этого я получил это:

lambda_problem

Так как вы можете видеть, что линия с «END» не уникальна, почему?

+0

Где находится Distinct()? – Hakunamatata

+1

Distinct() здесь не помогает, он удаляет только все ссылки (idx = 8) line – whizzzkey

+0

Это не уникально, потому что это одна и та же строка каждый раз. Индекс находит первое вхождение строки. Существует перегрузка, которая берет начальную позицию: https://msdn.microsoft.com/en-us/library/5xkyx09y(v=vs.110).aspx – briantyler

ответ

4

a.IndexOf(b) возвращает индекс первого вхождения b в пределах a, поэтому индекс === END === всегда одинаковый.

Вместо этого вы можете использовать an overload of Select, который принимает Func<TSource, int, TResult> в качестве параметра, чтобы вы могли получить индекс элемента.

var myQuery = lines 
    .Select((l, i) => new {idx = i, body = l}) 
    .Where(l => l.body.StartsWith("=") && l.body.EndsWith("=")); 
+0

thx, теперь он работает! – whizzzkey

0

Ваша проблема в том, что все строки END имеют идентичную строку, поэтому все вызовы lines.IndexOf(..) возвращают первый соответствующий экземпляр. Вам необходимо ввести новый метод (возможно назвать его NextIndexOf, которая принимает список и поддерживает счетчик последнего индекса, он вернулся.

Каждый последующий вызов NextIndexOf бы начать смотреть, откуда он вышел в прошлый раз.

+0

ok Я получаю точку, thx для вашего ответа – whizzzkey

1

Вы можете иметь различный индекс с помощью выбора первых и затем делать где

var myQuery = lines.Select((l,idx) => new {idx = idx, body = l}).Where(m => m.body.StartsWith("=") && m.body.EndsWith("=")); 

Вот скрипач:. https://dotnetfiddle.net/JW7S1s

Edit:. Ответ обновляется в соответствии с комментарием

+0

thx, я попробую его – whizzzkey

+1

Select имеет перегрузку, которая обеспечивает целое число как второй аргумент лямбда. Не сворачивайте свои собственные строки 'index ++' bit.Select ((l, ix) => new {idx = ix, body = l}). Где (m => ...) ' – pinkfloydx33

+0

@ pinkfloydx33 Nice one ! – Hakunamatata