将文本文件中的每个句子放入数组中,但检测标题/标题

时间:2015-01-23 00:10:39

标签: c# arrays regex string replace

我需要将文本文档/字符串中的每个句子都放到数组中。

问题在于如何处理标题,标题等文本部分,这些部分不是句子的一部分,但不以句号结尾“。”来检测。 无法检测到这些将导致他们被困在下一句话的前面(如果我使用“。”来区分句子),这是我不可能发生的。

最初我打算使用:

contentRefined = content.Replace(" \n", ". ");

我认为会删除所有空行和换行符,并在标题的末尾放置句点以便检测并将其视为句子,这将导致“。”但我可以再次替换它们没有。

但是没有工作它只是留下了完整的空行,只是在空行的开头放了一个“。”......以及每个段落开头的“。”

我现在尝试过:

contentRefined = Regex.Replace(content, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);

完全删除完整的空行,但不会让我更接近在标题的末尾添加句点。

我需要将句子和标题/标题放在一个数组中,我不确定是否有一种方法可以做到这一点,而不必将字符串拆分为“。”

编辑:显示我如何从文件中获取测试的完整当前代码

 public void sentenceSplit()
    {
        content = File.ReadAllText(@"I:\Project\TLDR\Test Text.txt");
        contentRefined = Regex.Replace(content, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);
        //contentRefined = content.Replace("\n", ". ");
    }

1 个答案:

答案 0 :(得分:0)

我假设'标题'和'标题'在他们自己的行上并且不会在一段时间内结束。

如果是这种情况,那么这可能对您有用:

var filePath = @"C:\Temp\temp.txt";
var sentences = new List<string>();

using (TextReader reader = new StreamReader(filePath))
{
    while (reader.Peek() >= 0)
    {
        var line = reader.ReadLine();

        if (line.Trim().EndsWith("."))
        {
            line.Split(new[] {'.'}, StringSplitOptions.RemoveEmptyEntries)
                .ToList()
                .ForEach(l => sentences.Add(l.Trim() + "."));
        }
    }
}

// Output sentences to console
sentences.ForEach(Console.WriteLine);

<强>更新

使用File.ReadAllLines()方法并在RichTextBox中显示句子的另一种方法:

private void Form1_Load(object sender, EventArgs e)
{
    var filePath = @"C:\Temp\temp.txt";

    var sentences = File.ReadAllLines(filePath)
        // Only select lines that end in a period
        .Where(l => l.Trim().EndsWith("."))
        // Split each line into sentences (one line may have many sentences)
        .SelectMany(s => s.Split(new[] {'.'}, StringSplitOptions.RemoveEmptyEntries))
        // Trim any whitespace off the ends of the sentence and add a period to the end
        .Select(s => s.Trim() + ".")
        // And finally cast it to a List (or you could do 'ToArray()')
        .ToList();

    // To show each sentence in the list on it's own line in the rtb:
    richTextBox1.Text = string.Join("\n", sentences);

    // Or to show them all, one after another:
    richTextBox1.Text = string.Join(" ", sentences);
}

<强>更新

现在我觉得我明白你在问什么,这就是我要做的。首先,我会创建一些类来管理所有这些东西。如果您将文档分解为多个部分,则会出现类似的内容:

  

HEADER

     

第一句。第二句。段   句子中有一个数字,就像在这句话中所说:“5.00美元不会如此   就像以前一样“。

     

空栏目标题

     

多个段落的标题

     

第一句。段   第二句。第三段有一个数字,就像在这里一样   引用:“5.00美元并没有像以前那样”。

     

第一句。第二句。段落句子   三个有一个数字,就像在这句话中所说:“5.00美元并没有达到   它习惯于“。

     

第一句。第二句。段落句子   三个有一个数字,就像在这句话中所说:“5.00美元并没有达到   它习惯于“。

所以我会创建以下类。首先,一个代表一个'部分'。这是由标题和零到多段落定义的:

private class Section
{
    public string Header { get; set; }

    public List<Paragraph> Paragraphs { get; set; }

    public Section()
    {
        Paragraphs = new List<Paragraph>();
    }
}

然后我会定义一个段落,其中包含一个或多个句子:

private class Paragraph
{
    public List<string> Sentences { get; set; }

    public Paragraph()
    {
        Sentences = new List<string>();
    }
}

现在我可以填充一个章节列表来代表文档:

var filePath = @"C:\Temp\temp.txt";

var sections = new List<Section>();
var currentSection = new Section();
var currentParagraph = new Paragraph();

using (TextReader reader = new StreamReader(filePath))
{
    while (reader.Peek() >= 0)
    {
        var line = reader.ReadLine().Trim();

        // Ignore blank lines
        if (string.IsNullOrWhiteSpace(line)) continue;

        if (line.EndsWith("."))
        {
            // This line is a paragraph, so add all the sentences
            // it contains to the current paragraph
            line.Split(new[] {". "}, StringSplitOptions.RemoveEmptyEntries)
                .Select(l => l.Trim().EndsWith(".") ? l.Trim() : l.Trim() + ".")
                .ToList()
                .ForEach(l => currentParagraph.Sentences.Add(l));

            // Now add this paragraph to the current section
            currentSection.Paragraphs.Add(currentParagraph);

            // And set it to a new paragraph for the next loop
            currentParagraph = new Paragraph();
        }
        else if (line.Length > 0)
        {
            // This line is a header, so we're starting a new section.
            // Add the current section to our list and create a 
            // a new one, setting this line as the header.
            sections.Add(currentSection);
            currentSection = new Section {Header = line};
        }
    }

    // Finally, if the current section contains any data, add it to the list
    if (currentSection.Header.Length > 0 || currentSection.Paragraphs.Any())
    {
        sections.Add(currentSection);
    }
}

现在我们将整个文档放在一个部分列表中,我们知道它们包含的顺序,标题,段落和句子。作为如何分析它的一个例子,这里有一种方法可以将它写回RichTextBox

// We can build the document section by section
var documentText = new StringBuilder();

foreach (var section in sections)
{
    // Here we can display headers and paragraphs in a custom way.
    // For example, we can separate all sections with a blank line:
    documentText.AppendLine();

    // If there is a header, we can underline it
    if (!string.IsNullOrWhiteSpace(section.Header))
    {
        documentText.AppendLine(section.Header);
        documentText.AppendLine(new string('-', section.Header.Length));
    }

    // We can mark each paragraph with an arrow (--> )
    foreach (var paragraph in section.Paragraphs)
    {
        documentText.Append("--> ");

        // And write out each sentence, separated by a space
        documentText.AppendLine(string.Join(" ", paragraph.Sentences));
    }
}

// To make the underline approach above look
// half-way decent, we need a fixed-width font
richTextBox1.Font = new Font(FontFamily.GenericMonospace, 9);

// Now set the RichTextBox Text equal to the StringBuilder Text
richTextBox1.Text = documentText.ToString();