【问题标题】:Extract the noun words & original sentence from POS Tag从词性标签中提取名词词和原句
【发布时间】:2013-09-30 13:57:15
【问题描述】:

我想从句子中提取名词,从词性标签中取回原句

 //Extract the words before _NNP & _NN from below  and also how to get back the original sentence from the Pos TAG. 
 Original Sentence:Hi. How are you? This is Mike·
 POSTag: Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NN

我试过这样的

    String txt = "Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NN";


    String re1 = "((?:[a-z][a-z0-9_]*))";   // Variable Name 1
    String re2 = ".*?"; // Non-greedy match on filler
    String re3 = "(_)"; // Any Single Character 1
    String re4 = "(NNP)";   // Word 1

    Pattern p = Pattern.compile(re1 + re2 + re3 + re4, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(txt);
    if (m.find()) {
        String var1 = m.group(1);
        System.out.print(  var1.toString()  );
    }
}

输出:嗨 但我需要一个句子中所有名词的列表。

【问题讨论】:

  • 你有没有尝试过? [a-zA-Z](?=[.]_NN) 将捕获任何 alphachar 字符串,然后是 ._NN,也许你可以从它开始。
  • 您的示例中有错字。在第一个街区,“迈克”。后面是“_NN”,但在第二个块中,后面是“_NNP”。
  • 这是一种名词,它是专有名词我得到了 pos 标签,它给了我不同类型的名词

标签: java regex nlp opennlp


【解决方案1】:

要提取名词,您可以这样做:

public static String[] extractNouns(String sentenceWithTags) {
    // Split String into array of Strings whenever there is a tag that starts with "._NN"
    // followed by zero, one or two more letters (like "_NNP", "_NNPS", or "_NNS")
    String[] nouns = sentenceWithTags.split("_NN\\w?\\w?\\b");
    // remove all but last word (which is the noun) in every String in the array
    for(int index = 0; index < nouns.length; index++) {
        nouns[index] = nouns[index].substring(nouns[index].lastIndexOf(" ") + 1)
        // Remove all non-word characters from extracted Nouns
        .replaceAll("[^\\p{L}\\p{Nd}]", "");
    }
    return nouns;
}

要提取原句,可以这样做:

public static String extractOriginal(String sentenceWithTags) {
    return sentenceWithTags.replaceAll("_([A-Z]*)\\b", "");
}

证明它有效:

public static void main(String[] args) {
    String sentence = "Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NN";
    System.out.println(java.util.Arrays.toString(extractNouns(sentence)));
    System.out.println(extractOriginal(sentence));
}

输出:

[Hi, Mike]
Hi. How are you? This is Mike.

注意:对于从提取的名词中删除所有非单词字符(如标点符号)的正则表达式,我使用了 this Stack Overflow question/answer

【讨论】:

  • 感谢您的回复詹姆斯,它非常适合名词 NN,但我需要所有这些 NN - 名词,单数或质量,NNP-专有名词,单数,NNPS-专有名词,复数,NNS -名词,复数,这不是句子中的错字。
  • 我修正了错字,但是我将如何拆分不同的名词,因为目前它只拆分以 _NN 结尾的名词,我还需要提取带有 _NNP、_NNPS、_NNS 的名词。
  • @srp 哦,好的。在这种情况下,只需添加 "\\w?\\w?"到正则表达式“_NN\\b”的末尾。 "\\w" 找到一个单词字符,而 "?"表示出现零次或一次,因此这将找到“_NN”后跟零个、一个或两个单词字符。正在更新答案。
  • @srp 编辑:在 extractOriginal() 方法中修改了正则表达式,现在更加健壮了。
  • @James,您在 cmets 中说过 // 删除数组中每个字符串中除最后一个单词(即名词)之外的所有单词,这是一直将最后一个单词添加到名词数组中即使那不是名词,也不一定每次最后一个词都是名词。我将如何消除这种情况?你能告诉我吗
【解决方案2】:

使用while (m.find()) 而不是if (m.find()) 来遍历所有匹配项。

此外,您的正则表达式可以真正简化:

  • 如果您不需要捕获数据,请不要加括号(通常)
  • 您使用的是((?:...)),这很奇怪:直接嵌套在捕获组中的非捕获组没有意义。
  • 我不确定.*? 部分是否符合您的预期。如果要匹配点,请改用[.]

因此,请改用([a-z][a-z0-9_]*)[.]_NNP

或者甚至使用正向前瞻:[a-z][a-z0-9_]*(?=[.]_NNP)。使用m.group() 访问捕获的数据。

【讨论】:

    【解决方案3】:

    这个应该可以的

    import java.util.ArrayList;
    public class Test {
    
    public static final String NOUN_REGEX = "[a-zA-Z]*_NN\\w?\\w?\\b";
    
    public static ArrayList<String> extractNounsByRegex(String sentenceWithTags) {
        ArrayList<String> nouns = new ArrayList<String>();
        String[] words = sentenceWithTags.split("\\s+");
        for (int i = 0; i < words.length; i++) {
            if(words[i].matches(NOUN_REGEX)) {
                System.out.println(" Matched ");
                //remove the suffix _NN* and retain  [a-zA-Z]*
                    nouns.add(words[i].replaceAll("_NN\\w?\\w?\\b", ""));
                }
            }
            return nouns;
        }
    
        public static String extractOriginal(String word) {
                    return word.replaceAll("_NN\\w?\\w?\\b", "");
        }
    
        public static void main(String[] args) {
            //        String sentence = "Hi._NNP How_WRB are_VBP you?_JJ This_DT is_VBZ Mike._NN";
            String sentence = "Eiffel_NNP tower_NN is_VBZ in_IN paris_NN Hi_NNP How_WRB are_VBP you_PRP This_DT is_VBZ Mike_NNP Barrack_NNP Obama_NNP is_VBZ a_DT president_NN this_VBZ";
            System.out.println(extractNounsByRegex(sentence).toString());
            System.out.println(sentence);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多