I strongly suspect a regular loop will be your best option. But if you really want to force it:
IEnumerable<string> headerLinesWithCounts = source
.Select((value, index) => (value: value, index: index))
.Where(pair => pair.value[0] == 'H')
.Select(pair => (value: pair.value, lines: source.Skip(pair.index + 1).TakeWhile(v => v[0] != 'H')))
.Select(pair => $"{pair.value},{pair.lines.Count()}");
Output:
H,1000,28-09-2017,2
H,200,29-09-2017,3
Or, if you need to include the lines in the output as well:
IEnumerable<string> headerLinesWithCounts = source
.Select((value, index) => (value: value, index: index))
.Where(pair => pair.value[0] == 'H')
.Select(pair => (value: pair.value, lines: source.Skip(pair.index + 1).TakeWhile(v => v[0] != 'H')))
.Select(pair => (header: $"{pair.value},{pair.lines.Count()}", lines: pair.lines))
.SelectMany(pair => Enumerable.Repeat(pair.header, 1).Concat(pair.lines));
Output:
H,1000,28-09-2017,2
L,30,Pete
L,50,Pete
H,200,29-09-2017,3
L,35,Pete
L,45,Pete
L,55,Pete
NB: This is using the new
ValueTuple[
^] type. If your compiler doesn't support it, you can use anonymous types instead.