【问题标题】:how to identify a end of a sentence如何识别句子的结尾
【发布时间】:2014-11-02 21:55:18
【问题描述】:
String x=" i am going to the party at 6.00 in the evening. are you coming with me?";

如果我有上述字符串,我需要通过使用句子边界标点符号(如 . 和 ?)将其分解为句子

但它不应该在 6 处拆分句子,因为那里有一个指针。有没有办法确定java中正确的句子边界位置是什么?我曾尝试在 java.util pakage 中使用 stringTokenizer,但它总是在找到指针时打破句子。有人可以建议我正确执行此操作的方法吗?

这是我尝试将文本标记为句子的方法。

public static ArrayList<String> sentence_segmenter(String text) {
    ArrayList<String> Sentences = new ArrayList<String>();

    StringTokenizer st = new StringTokenizer(text, ".?!");
    while (st.hasMoreTokens()) {

        Sentences.add(st.nextToken());
    }
    return Sentences;
}

我也有一种将句子分割成短语的方法,但是当程序发现逗号(,)时,它也会分割文本。但是当有像 60,000 这样中间有逗号的数字时,我不需要拆分它。以下是我用来分割短语的方法。

   public static ArrayList<String> phrasesSegmenter(String text) {
    ArrayList<String> phrases = new ArrayList<String>();
    StringTokenizer st = new StringTokenizer(text, ",");
    while (st.hasMoreTokens()) {
        phrases.add(st.nextToken());
    }
    return phrases;
}

【问题讨论】:

标签: java regex nlp tokenize


【解决方案1】:

来自documentation of StringTokenizer

StringTokenizer 是一个遗留类,出于兼容性原因保留,但不鼓励在新代码中使用它。建议任何寻求此功能的人使用 String 的 split 方法或 java.util.regex 包。

如果您使用拆分,您可以使用任何正则表达式将文本拆分为句子。您可能想要 ?!. 中的任何一个,以及空格或文本结尾:

text.split("[?!.]($|\\s)")

【讨论】:

  • 但是如何识别正确的分割sentect的位置。如果句子中间有十进制数。那么有那里的句号不能作为句末。我需要知道如何处理这些情况@fejese
  • 这是一个正则表达式提琴手:regex101.com/r/vB7gU9/1 请注意,我删除了空格字符匹配器 (\s) 的双重转义,并在开头添加了一个 .*? 以使其更可见作为拆分后的第一个元素返回
  • 仍然没有得到我的答案。 @fejese 你的正则表达式不工作
  • @fejese 谢谢哥们。它现在工作。但是我遇到了另一个问题,我已经编辑了我的帖子,你能检查一下并给我一个解决方案吗?非常感谢。
  • 如果您发现我的回答适合您的问题,请接受它,如果您还有其他新问题,请打开一个新问题。但是,您最近的问题与原始问题完全相同。花一些时间来了解这个答案中的解决方案为什么以及如何工作,它应该很容易适应您的新问题。
【解决方案2】:

这是我对问题的解决方案。

/** tries to decide if a there's a sentence-end in index i of a given text

 * @param text
 * @param i
 * @return
 */
public static boolean isSentenceEnd(String text, int i) {
    char c = text.charAt(i);
    return isSentenceEndChar(c) && !isPeriodWord(text, i);
} 
/**
 * PeriodWords are words such as 'Dr.' or 'Mr.'
 *
 * @param text - the text to examoine.
 * @param i - index of the priod '.' character
 * @return
 */
private static String[] periodWords = { "Mr.", "Mrs.", "Ms.", "Prof.", "Dr.", "Gen.", "Rep.", "Sen.", "St.",
                "Sr.", "Jr.", "Ph.", "Ph.D.", "M.D.", "B.A.", "M.A.", "D.D.", "D.D.S.",
                "B.C.", "b.c.", "a.m.", "A.M.", "p.m.", "P.M.", "A.D.", "a.d.", "B.C.E.", "C.E.",
                "i.e.", "etc.", "e.g.", "al."};
private static boolean isPeriodWord(String text, int i) {
    if (i < 4) return true;
    if (text.charAt(i-2) == ' ') return true; // one char words are definetly priodWords
    String txt = text.substring(0, i);
    for (String pword: periodWords) {
        if (txt.endsWith(pword)) return true;
    }
    if (txt.matches("^.*\\d\\.$")) return true; // dates seperated with "." or numbers with fraction
    return false;
}

private static final char[] sentenceEndChars = {'.', '?', '−'};
private static boolean isSentenceEndChar(char c) {
    for (char sec : sentenceEndChars) {
        if (c == sec) return true;
    }
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多