使用C#删除字符串中的最后两行?
我想从我拥有的一些总是变化的字符串中删除最后两行:使用C#删除字符串中的最后两行?,c#,linq,C#,Linq,我想从我拥有的一些总是变化的字符串中删除最后两行: Hello How Are you ? im fine Thanks some info some info 对于这个例子,假设我有上面的字符串 我想删除最后两行 “一些信息” 这就是我在下面尝试的 正如我所说的,最后两行总是以文本形式出现,这就是为什么我使用“Environment.NewLine” string sem = mtstring = mtstring (mtstring .TrimEnd().LastIndexOf(Envir
Hello How Are you ?
im fine Thanks
some info
some info
对于这个例子,假设我有上面的字符串
我想删除最后两行
“一些信息”
这就是我在下面尝试的
正如我所说的,最后两行总是以文本形式出现,这就是为什么我使用“Environment.NewLine”
string sem = mtstring = mtstring (mtstring .TrimEnd().LastIndexOf(Environment.NewLine));
string Good = sem = sem.Remove(sem.TrimEnd().LastIndexOf(Environment.NewLine));
改为:
string sem = mtstring.Remove(mtstring.LastIndexOf(Environment.NewLine));
string Good = sem.Remove(sem.LastIndexOf(Environment.NewLine));
假设您有
Environment.NewLine
作为分隔符,但也可以更改为使用任何分隔符
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
n.b.注意新行,在Windows上,它是
\r\n
。Unix和Mac分别为\n
和\r
这里有一条单行线:
string good = string.Join(Environment.NewLine, mtstring.Split(Environment.NewLine).Reverse().Skip(2).Reverse());
编辑:
我做了下面的测试来测试时间效率,这表明(正如@TheodorZoulias所指出的)这种方法是非常无效的,所以在更大的数据集上使用因果关系
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");
}
}
输出:
Hello How Are you ?
im fine Thanks
字符串长度:9888886
时间:45毫秒
字符串长度:9888876
时间:188毫秒
总之,double
Reverse
调用非常昂贵,与仅拆分和连接字符串相比,执行时间增加了四倍,这本身并不是一项廉价的任务。您可以尝试以下方法:
//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);
快速(写入而非执行)解决方案是使用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());
更理想的解决方案是使用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();
var sb=new StringBuilder();
var temp=input.Split(Environment.NewLine.ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
对于(变量i=0;i<温度长度-2;++i)
某人(临时工[本人]);
var res2=sb.ToString();
机器人res1
和res2
将:
你好吗?我很好,谢谢
为提高效率而实施。希望不是马车
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);
}
如果添加Microsoft的“System.Interactive”NuGet软件包,则可以执行以下操作:
string Good =
String.Join(
Environment.NewLine,
mtstring.Split(Environment.NewLine.ToArray()).SkipLast(2));
Environment.NewLine!=Random.Text
-很清楚,“新行”在某种程度上就是这样的,ala\r\n
。不是一堆随机的文本。可能是重复的,我不是故意要随机上课……这似乎效率很低。Reverse为源代码创建了一个缓冲区,您调用了它两次。我认为您的说法不对,因为Reverse
使用延迟执行,因此对象实际上并不包含所有数据,只包含执行它所需的数据。我做了一个测试,看到我编辑的答案。你可以查看反向的实现。它所做的是缓冲源的所有元素,然后向后枚举缓冲区。当然,您是正确的。谢谢你纠正我,我已经更新了我的测试和结论。我确实知道这次讨论中提供的所有事实,但从一些额外的(和未满足的)假设中得出了所有错误的结论。哈哈!是的,LINQ的延迟执行很棘手。它仍然不时地咬我。:-)你的最新答案现在是有价值的,向上投票。酷。的实现很有趣。它使用一个缓冲区,缓冲区大小为要跳过的行的大小。
string Good =
String.Join(
Environment.NewLine,
mtstring.Split(Environment.NewLine.ToArray()).SkipLast(2));