我正在尝试从段落创建“片段”。我有一段很长的文字,中间有一个单词。我想得到包含该行之前的单词以及该行之后的行的行。
我有以下资料:
\n
其他一些标准:
以下是一个例子:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
This is the 5th line of RABBIT text in the paragraph
例如,如果我的索引指向BIRD,它应该显示第1,2和1行。 3作为一个完整的字符串,如下所示:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
如果我的索引指向DOG,则应显示第3,4行和第3行。 5作为一个完整的字符串,如下所示:
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
This is the 5th line of RABBIT text in the paragraph
等
有人想帮忙解决这个问题吗?
答案 0 :(得分:3)
在我看来,这是使用StringReader
课程的绝佳机会:
Queue<string>
)中,在读取了一定数量的线条之后丢弃您不需要的线条。在我看来,这比其他方法有一些优势:
String.Split
,它不会比您需要的更多更多工作 - 即,读取整个字符串以查找要拆分的字符,并创建一个子串的数组。TextReader
(例如,StreamReader
来处理任何文本输入,甚至可以很轻松地重构它 - 所以它甚至可以处理大文件,没有必须将给定文件的全部内容加载到内存中。想象一下这种情况:您希望从包含小说中整个文本的文本文件中找到一段文本摘录。 (这不是你的情景 - 我只是假设地说。)使用String.Split
将要求根据你指定的分隔符分割小说的整个文本,而使用一个StringReader
(在这种情况下,StreamReader
)只需要阅读,直到找到所需的文本,此时将返回摘录。
同样,我意识到这不一定是你的场景 - 只是建议这种方法提供可扩展性作为其优势之一。
这是一个快速实施:
// rearranged code to avoid horizontal scrolling
public static string FindSurroundingLines
(string haystack, string needle, int paddingLines) {
if (string.IsNullOrEmpty(haystack))
throw new ArgumentException("haystack");
else if (string.IsNullOrEmpty(needle))
throw new ArgumentException("needle");
else if (paddingLines < 0)
throw new ArgumentOutOfRangeException("paddingLines");
// buffer needs to accomodate paddingLines on each side
// plus line containing the needle itself, so:
// (paddingLines * 2) + 1
int bufferSize = (paddingLines * 2) + 1;
var buffer = new Queue<string>(/*capacity*/ bufferSize);
using (var reader = new StringReader(haystack)) {
bool needleFound = false;
while (!needleFound && reader.Peek() != -1) {
string line = reader.ReadLine();
if (buffer.Count == bufferSize)
buffer.Dequeue();
buffer.Enqueue(line);
needleFound = line.Contains(needle);
}
// at this point either the needle has been found,
// or we've reached the end of the text (haystack);
// all that's left to do is make sure the string returned
// includes the specified number of padding lines
// on either side
int endingLinesRead = 0;
while (
(reader.Peek() != -1 && endingLinesRead++ < paddingLines) ||
(buffer.Count < bufferSize)
) {
if (buffer.Count == bufferSize)
buffer.Dequeue();
buffer.Enqueue(reader.ReadLine());
}
var resultBuilder = new StringBuilder();
while (buffer.Count > 0)
resultBuilder.AppendLine(buffer.Dequeue());
return resultBuilder.ToString();
}
}
一些示例输入/输出(text
包含您的示例输入):
代码:
Console.WriteLine(FindSurroundingLines(text, "MOUSE", 1);
输出:
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
代码:
Console.WriteLine(FindSurroundingLines(text, "BIRD", 1);
输出:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
代码:
Console.WriteLine(FindSurroundingLines(text, "DOG", 0);
输出:
This is the 4th line of DOG text in the paragraph
代码:
Console.WriteLine(FindSurroundingLines(text, "This", 2);
输出:
This is the 1st line of CAT text in the paragraph
This is the 2nd line of BIRD text in the paragraph
This is the 3rd line of MOUSE text in the paragraph
This is the 4th line of DOG text in the paragraph
This is the 5th line of RABBIT text in the paragraph
答案 1 :(得分:2)
使用LINQ扩展方法获取正确的字符串:
string[] lines = text.Split('\n');
// Find the right line to work with
int position = 0;
for (int i = 0; i < lines.Count(); i++)
if (lines[i].Contains(args[0]))
position = i - 1;
// Get in range if we had a match in the first line
if (position == -1)
position = 0;
// Adjust the line index so we have 3 lines to work with
if (position > lines.Count() - 3)
position = lines.Count() - 3;
string result = String.Join("\n", lines.Skip(position).Take(3).ToArray());
这当然可以通过在找到索引后立即退出for循环来进行优化,并且可能还有许多其他事情。你甚至可以LINQify,所以你永远不需要实际存储额外的数组,但我现在想不出一个好方法。
对位置检查的另一种选择可能是position = Math.Max(0,Math.Min(position, lines.Count() - 3));
- 它会同时处理它们。
答案 2 :(得分:1)
有几种方法可以解决这个问题:
第一种方法: 使用String.IndexOf()和String.LastIndexOf()。
您可以使用TextBox.SelectionStart()找到当前所选单词的位置。然后只需从选择位置查找LastIndexOf,找到'\ n'以找到上一行(不要从选择中获取第一个lastindexof,一旦找到一个...再从该位置再次执行,这样你就可以获得该行的开头)。然后从选择点开始,仅使用IndexOf找到'\ n'以获得行的结尾。再一次,不要使用你找到的第一个,从第一个找到的位置重复它以获得第二行的结束。然后简单地用你找到的区域对文本进行子串。
第二种方法:按'\ n'字符使用String.Split()(创建一个字符串数组,每个字符串按照数组索引的顺序包含与文本不同的行)。找到文本所在行的索引,然后简单地从字符串[index]中获取该行之前,之后和之后的行。希望这两种方法足够清晰,可以让你弄清楚你的编码。如果你仍然被困住,请告诉我。
答案 3 :(得分:0)
好的。勒梅有裂缝,
我认为我要做的第一件事就是将所有内容分成数组。因为那时我们有一种简单的方法来“计算”线条。
string[] lines = fullstring.Split('\n');
一旦我们拥有了这个,不幸的是我不知道任何索引通过数组中的每个点。可能有一个,但没有在互联网上拖网,我只会去
int i = -1;
string animal = 'bird';
foreach(string line in lines)
{
i++;
if(line.indexof(animal) > -1) break;
}
// we will need a if(i == -1) then we didn't find the animal etc
好的,我们现在有了这条线。我们需要做的就是......
if(i == 0)
{
writeln(lines[0);
writeln(lines[1]);
etc
}
else
if(i == lines.count - 1)
{
//this means last array index
}
else
{
//else we are in the middle. So just write out the i -1, i, i+1
}
我知道那太乱了。但这就是我如何解决这个问题。