Take the last n lines of a C # line

I have a string of unknown length

it is in format

\nline \nline \nline 

I donโ€™t know how long I can just take the last 10 lines of a line, a line separated by "\ n"

+8
string c # string-parsing
source share
6 answers

As the line gets larger, it becomes more important to avoid handling characters that don't matter. Any approach using string.Split inefficient, since the entire string needs to be processed. An effective solution should go through the line from the back. This uses the regex approach.

Note that it returns a List<string> because the results must be undone before they are returned (hence using the Insert method)

 private static List<string> TakeLastLines(string text, int count) { List<string> lines = new List<string>(); Match match = Regex.Match(text, "^.*$", RegexOptions.Multiline | RegexOptions.RightToLeft); while (match.Success && lines.Count < count) { lines.Insert(0, match.Value); match = match.NextMatch(); } return lines; } 
+9
source share
 var result = text.Split('\n').Reverse().Take(10).ToArray(); 
+7
source share

Split() string in \n and take the last 10 elements of the resulting array.

+6
source share

If it is a file, and the file is especially large, you can do it efficiently. The way to do this is to read the file back and then take only the first 10 lines. You can see an example of using the Jon Skeet MiscUtil library to do it here .

 var lines = new ReverseLineReader(filename); var last = lines.Take(10); 
+3
source share

Here's one way to do this, which has the advantage that it doesn't create copies of the entire source string, is so pretty efficient. Most of the code will be placed in a class along with other general-purpose extension methods, so the end result is that you can do this with 1 line of code

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string x = "a\r\nb\r\nc\r\nd\r\ne\r\nf\r\ng\r\nh\r\ni\r\nj\r\nk\r\nl\r\nm\r\nn\r\no\r\np"; foreach(var line in x.SplitAsEnumerable("\r\n").TakeLast(10)) Console.WriteLine(line); Console.ReadKey(); } } static class LinqExtensions { public static IEnumerable<string> SplitAsEnumerable(this string source) { return SplitAsEnumerable(source, ","); } public static IEnumerable<string> SplitAsEnumerable(this string source, string seperator) { return SplitAsEnumerable(source, seperator, false); } public static IEnumerable<string> SplitAsEnumerable(this string source, string seperator, bool returnSeperator) { if (!string.IsNullOrEmpty(source)) { int pos = 0; do { int newPos = source.IndexOf(seperator, pos, StringComparison.InvariantCultureIgnoreCase); if (newPos == -1) { yield return source.Substring(pos); break; } yield return source.Substring(pos, newPos - pos); if (returnSeperator) yield return source.Substring(newPos, seperator.Length); pos = newPos + seperator.Length; } while (true); } } public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count) { List<T> items = new List<T>(); foreach (var item in source) { items.Add(item); if (items.Count > count) items.RemoveAt(0); } return items; } } } 

EDIT: It has been pointed out that this may be more efficient as iterates over the entire string. I also believe that RemoveAt (0) with a list is probably also inefficient. To solve this problem, the code can be modified to search backward by string. This would eliminate the need for a TakeLast function, since we could just use Take.

0
source share

Effective space approach

  private static void PrintLastNLines(string str, int n) { int idx = str.Length - 1; int newLineCount = 0; while (newLineCount < n) { if (str[idx] == 'n' && str[idx - 1] == '\\') { newLineCount++; idx--; } idx--; } PrintFromIndex(str, idx + 3); } private static void PrintFromIndex(string str, int idx) { for (int i = idx; i < str.Length; i++) { if (i < str.Length - 1 && str[i] == '\\' && str[i + 1] == 'n') { Console.WriteLine(); i++; } else { Console.Write(str[i]); } } Console.WriteLine(); } 
0
source share

All Articles