简体   繁体   中英

Delete Last 2 Lines in string using C#?

i wonder to delete last 2 lines from some string i have that always change:

Hello How Are you ?
im fine Thanks
some info
some info

for the example lets say i have the string above i want to delete the last 2 lines "some info"

thats what i tried below as i said the last two lines have always ranom text thats why i used 'Environment.NewLine'

string sem = mtstring = mtstring (mtstring .TrimEnd().LastIndexOf(Environment.NewLine));
            string Good = sem = sem.Remove(sem.TrimEnd().LastIndexOf(Environment.NewLine));

Here's a oneliner:

string good = string.Join(Environment.NewLine, mtstring.Split(Environment.NewLine).Reverse().Skip(2).Reverse());

Edit:

I did the following test to test the time efficiency, which shows that (as pointed out by @TheodorZoulias) this approach is quite ineffecient, so use with causion on larger data sets.

class Program
{
  static void Main(string[] args)
  {
    var testString = string.Join(Environment.NewLine, Enumerable.Range(0, 1000000));
    var oldArray = testString.Split();

    Stopwatch stopwatch = Stopwatch.StartNew();
    var newString = string.Join(Environment.NewLine, oldArray);
    stopwatch.Stop();
    Console.WriteLine($"String length: {newString.Length}");
    Console.WriteLine($"Time elapsed: {stopwatch.ElapsedMilliseconds} ms");

    stopwatch = Stopwatch.StartNew();
    newString = string.Join(Environment.NewLine, oldArray.Reverse().Skip(2).Reverse());
    stopwatch.Stop();
    Console.WriteLine($"String length: {newString.Length}");
    Console.WriteLine($"Time elapsed: {stopwatch.ElapsedMilliseconds} ms");
  }
}

Output:

String length: 9888886

Time elapsed: 45 ms

String length: 9888876

Time elapsed: 188 ms

To summarize, the double Reverse call is quite expensive, quadrupling the execution time compared to just splitting and joining the string, which in itself is no inexpensive task.

If you add in Microsoft's "System.Interactive" NuGet Package, you can do this:

string Good =
    String.Join(
        Environment.NewLine,
        mtstring.Split(Environment.NewLine.ToArray()).SkipLast(2));

change to:

string sem = mtstring.Remove(mtstring.LastIndexOf(Environment.NewLine));
string Good = sem.Remove(sem.LastIndexOf(Environment.NewLine));

The assumption is that you have Environment.NewLine as a separator but could be changed to use any separator as well

var str = "Hello How Are you ?" + Environment.NewLine +
          "im fine Thanks" + Environment.NewLine +
          "some info" + Environment.NewLine +
          "some info";

var split = str.Split(new [] { Environment.NewLine }, StringSplitOptions.None).ToList();

Console.WriteLine(string.Join(Environment.NewLine, split.Take(split.Count - 2)));
// Hello How Are you ?
// im fine Thanks

nb Be careful about the new line, on Windows, it is \\r\\n . Unix and Mac \\n and \\r respectively.

You could try something along the lines of:

//Create list of strings for each line in mtstring
List<string> lines = mtstring.Split(
                        new string[] {"\n", "\r"}, 
                        StringSplitOptions.None
                ).ToList();

//Take a subset of these lines (Total - 2)
lines = lines.GetRange(0, lines.Count-2);

//Rejoin the list as a string
string Good = string.Join("\n", lines);

Output:

Hello How Are you ?

im fine Thanks

Fast (to write, not execute) solution is to use Linq:

var input = "Hello How Are you ?\r\nim fine Thanks\r\nsome info\r\nsome info";
var res1 = string.Join(Environment.NewLine, input
    .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
    .Reverse()
    .Skip(2)
    .Reverse());

More optimal solution is to use a StringBuilder :

var sb = new StringBuilder();
var temp = input.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < temp.Length - 2; ++i)
    sb.AppendLine(temp[i]);

var res2 = sb.ToString();

Bot res1 and res2 will be:

Hello How Are you ?
im fine Thanks

Implementation for efficiency. Hopefully it's not buggy.

public static string RemoveLinesFromTheEnd(string source, int linesToRemove)
{
    var separators = new char[] { '\r', '\n' };
    int pos = source.Length;
    for (int i = 0; i < linesToRemove; i++)
    {
        pos = source.LastIndexOfAny(separators, pos - 1);
        if (pos > 0 && source[pos - 1] == '\r' && source[pos] == '\n') pos--;
        if (pos <= 0) break;
    }
    return pos < 0 ? "" : source.Substring(0, pos);
}

Usage:

var cleanString = RemoveLinesFromTheEnd(mtstring, 2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM