StringTokenizer в JAVA

StringTokenizer используется для токенизации теговой строки в JAVA. Строка помечается с использованием Parts Of Speech MaxentTagger из Стэнфорда. Подстрока тегового текста используется для итеративного отображения только тега POS и только слова.

Вот текст перед пометкой:

Человек всегда имел представление о том, что смелые поступки проявляются в физических действиях. Хотя это не совсем ошибочно, не существует единственного пути к доблести. С давних пор это признак силы, чтобы дать отпор дикому животному. Это понятно, если биться в обороне; однако пройти лишнюю милю и спровоцировать животное и бороться с ним - это самая низкая степень цивилизации, которую может продемонстрировать человек. Тем более, в наш век рассуждений и знаний. Традиция может называть это, но слепо придерживаться этого - идиотизм, будь то знаменитый Джалликатту в Тамил Наду (индийский эквивалент испанской корриды) или петушиные бои. Бросать камни в собаку и наслаждаться ее воем от боли ужасно. Если бы кто-то дал всего лишь струйку мысли и совести, проблема оказалась бы плачевной во всех аспектах. Животные играют роль вместе с нами в нашей экосистеме. И некоторые животные дороже: бродячие собаки, которые охраняют нашу улицу, умная ворона, зверь бремя и обычные животные пастбища. Литература озвучивала по-своему: "Властелин колец" общался с пони Билла Ферни с особой тщательностью; в "Гарри Поттере", когда они не прислушались к совету Гермионы по поводу обращения с домашними эльфами, они усвоили трудный путь, который вызвал их собственное уничтожение; и Джек Лондон, пишет все о животных. На самом деле, доброта к животным является добродетелью.

Вот текст с тегами POS:

Man_NN имеет_VBZ всегда_RB имел_VBN this_DT notion_NN that_IN храбрый_VBP deeds_NNS являются_VBP манифест_JJ in_IN физические_JJ действия_NNS ._. Хотя _IN it_PRP is_VBZ не_RB полностью_RB ошибочно_JJ,_, там_EX делает_VBZ n't_RB лежат_VB the_DT singular_JJ path_NN to_TO valor_NN ._. From_IN из_IN old_JJ,_, it_PRP is_VBZ a_DT знак_NN из_IN сила_NN к_TO fight_VB назад_RP a_DT wild_JJ animal_NN._. Это_ПР_VBZ понятно_JJ, если_IN сражался_ВБН в_ИН обороне_NN; _: однако_RB,_, to_TO go_VB More_RBR so_RB,_, in_IN this_DT age_NN из_IN рассуждений_NN и_CC знаний_NN ._. Tradition_NN may_MD call_VB it_PRP,_, but_CC adhering_JJ blindly_RB to_TO it_PRP is_VBZ idiocy_NN,_, be_VB it_PRP the_DT famed_JJ Jallikattu_NNP in_IN Tamil_NNP Nadu_NNP -LRB-_-LRB- The_DT Indian_JJ equivalent_NN to_TO the_DT Spanish_JJ Bullfighting_NN -RRB-_-RRB- or_CC the_DT cock-fights_NNS ._. Pelting_VBG stone_NNS at_IN a_DT dog_NN и_CC relishing_VBG it_PRP howl_NN in_IN pain_NN is_VBZ ужасно_JJ._. Если бы _IN one_CD only_RB дал_VBD as_RB much_JJ as_IN a_DT trickle_VB of_IN мысли_NN и_CC сознание_NN the_DT выпуск_NN will_MD поверхность_VB как_IN deplorable_JJ in_IN каждый_DT аспект_NN ._. Animals_NNS play_VBP a_DT part_NN вдоль_IN с_IN us_PRP in_IN our_PRP$ ecosystem_NN ._. И_CC,_, некоторые_DT животные_NNS являются_VBP дорогой_RBR:_: the_DT беспризорный_JJ собак_NNS, которые_WDT охраняют_VBP наши_PRP $ street_NN, _, _DT разумные_JJ crow_NN, _, _DT зверя_N___________ Literature_NN has_VBZ voiced_VBN in_IN its_PRP$ own_JJ way_NN:_: In_IN The_DT Lord_NN of_IN the_DT Rings_NNP the_DT fellowship_NN treated_VBN Bill_NNP Ferny_NNP 's_POS pony_NN with_IN utmost_JJ care_NN;_: in_IN Harry_NNP Potter_NNP when_WRB they_PRP did_VBD n't_RB heed_VB Hermione_NNP 's_POS advice_NN on_IN the_DT treatment_NN of_IN house_NN elves_NNS они_PRP узнали_VBD the_DT hard_JJ way_NN, которые_IN it_PRP вызвали_VBD их_PRP $ own_JJ отменить_NN;_: and_CC Jack_NNP Лондон_NNP,_, пишет_VBZ all_DT about_IN животных_NNS ._. Действительно_RB,_, Доброта_NN к_TO animal_NNS is_VBZ a_DT virtue_NN ._.

А вот код, который стремится получить вышеупомянутые подстроки:

String line;
StringBuilder sb=new StringBuilder();
try(FileInputStream input = new FileInputStream("E:\\D.txt"))
    {
    int data = input.read();
    while(data != -1)
        {
        sb.append((char)data);
        data = input.read();
        }
    }
catch(FileNotFoundException e)
{
    System.err.println("File Not Found Exception : " + e.getMessage());
}
line=sb.toString();
String line1=line;//Copy for Tagger
line+=" T";       
List<String> sentenceList = new ArrayList<String>();//TAGGED DOCUMENT
MaxentTagger tagger = new MaxentTagger("E:\\Installations\\Java\\Tagger\\english-left3words-distsim.tagger");
String tagged = tagger.tagString(line1);
File file = new File("A.txt");
BufferedWriter output = new BufferedWriter(new FileWriter(file));
output.write(tagged);
output.close();
DocumentPreprocessor dp = new DocumentPreprocessor("C:\\Users\\Admin\\workspace\\Project\\A.txt");
int largest=50;
int m=0;
StringTokenizer st1;
for (List<HasWord> sentence : dp) 
{
   String sentenceString = Sentence.listToString(sentence);
   sentenceList.add(sentenceString.toString());
}
String[][] Gloss=new String[sentenceList.size()][largest];
String[] Adj=new String[largest];
String[] Adv=new String[largest];
String[] Noun=new String[largest];
String[] Verb=new String[largest];
int adj=0,adv=0,noun=0,verb=0;
for(int i=0;i<sentenceList.size();i++)
{
    st1= new StringTokenizer(sentenceList.get(i)," ,(){}[]/.;:&?!");
    m=0;//Count for Gloss 2nd dimension
    //GETTING THE POS's COMPARTMENTALISED
    while(st1.hasMoreTokens())
    {
        String token=st1.nextToken();
        if(token.length()>1)//TO SKIP PAST TOKENS FOR PUNCTUATION MARKS
        {
        System.out.println(token);
        String s=token.substring(token.lastIndexOf("_")+1,token.length());
        System.out.println(s);
        if(s.equals("JJ")||s.equals("JJR")||s.equals("JJS"))
        {
            Adj[adj]=token.substring(0,token.lastIndexOf("_"));
            System.out.println(Adj[adj]);
            adj++;
        }
        if(s.equals("NN")||s.equals("NNS"))
        {
            Noun[noun]=token.substring(0,  token.lastIndexOf("_"));
            System.out.println(Noun[noun]);
            noun++;
        }
        if(s.equals("RB")||s.equals("RBR")||s.equals("RBS"))
        {
            Adv[adv]=token.substring(0,token.lastIndexOf("_"));
            System.out.println(Adv[adv]);
            adv++;
        }
        if(s.equals("VB")||s.equals("VBD")||s.equals("VBG")||s.equals("VBN")||s.equals("VBP")||s.equals("VBZ"))
        {
            Verb[verb]=token.substring(0,token.lastIndexOf("_"));
            System.out.println(Verb[verb]);
            verb++;
        }
        }
    }
    i++;//TO SKIP PAST THE LINES WHERE AN EXTRA UNDERSCORE OCCURS FOR FULLSTOP
 }

D.txt содержит простой текст.

Что касается вопроса:

Каждое слово размечается в пробелах. За исключением 'n't_RB', где он маркируется как n't и RB отдельно.

Вот как выглядит результат:

Man_NN
NN
Man
has_VBZ 
VBZ
has
always_RB
RB
always
had_VBN
VBN
had
this_DT
DT
notion_NN
NN
notion
that_IN
IN
brave_VBP
VBP
brave
deeds_NNS
NNS
deeds
are_VBP
VBP
are
manifest_JJ
JJ
manifest
in_IN
IN
physical_JJ
JJ
physical
actions_NNS
NNS
actions
While_IN
IN
it_PRP
PRP
is_VBZ
VBZ
is
not_RB
RB
not
entirely_RB
RB
entirely
erroneous_JJ
JJ
erroneous
there_EX
EX
does_VBZ
VBZ
does
n't
n't
RB
RB

Но если я просто запущу 'there_EX Does_VBZ n't_RB lie_VB' в токенизаторе, 'n't_RB' будет объединен. Когда я запускаю программу, я получаю исключение StringIndexOutOfBounds, которое понятно, потому что нет '_' в 'n't' или 'RB'. Кто-нибудь может посмотреть на это? Спасибо.

3 ответа

Решение

В документации DocumentPreprocessor сказано

ПРИМЕЧАНИЕ. Если используется пустой аргумент, предполагается, что документ токенизирован, а DocumentPreprocessor не выполняет токенизацию.

Поскольку документ, который вы загружаете из вашего файла, уже был размечен на первом шаге вашей программы, вы должны сделать:

DocumentPreprocessor dp = new DocumentPreprocessor("./data/stanford-nlp/A.txt");
dp.setTokenizerFactory(null);

Затем он выводит ' слова правильно, например

...
did_VBD
VBD
did
n't_RB
RB
n't
heed_VB
VB
heed
Hermione_NNP
NNP
's_POS
POS
...

Метод lastIndexOf при возникновении ошибки возвращает -1. Исключение, которое вы получаете, связано с методом подстроки, который вы используете, когда метод lastIndexOf не может получить правильный символ в вашей строке.

Я думаю, что вы можете сделать, чтобы проверить, если индекс отличается от -1, и после этого использовать его. С помощью этой проверки вы можете избежать той досадной ошибки, которую получаете. К сожалению, без всего вводимого текста действительно трудно понять, какие строки не содержат указанный вами символ.

Для полноты картины я думаю, что вам нужно исправить также способ получения всех элементов POS. На мой взгляд, матрица String подвержена ошибкам (вам необходимо выяснить, как управлять индексами), а также довольно неэффективна для такого рода задач.

Возможно, вы можете использовать Multimap, чтобы связать для каждого типа POS все элементы, которые к нему относятся. Я думаю, что таким образом вы можете управлять всем лучше.

Я постараюсь для String.split() скорее, чем StringTokenizer

String str = "Man_NN has_VBZ always_RB had_VBN this_DT notion_NN that_IN brave_VBP deeds_NNS are_VBP manifest_JJ in_IN physical_JJ actions_NNS ._. While_IN it_PRP is_VBZ not_RB entirely_RB erroneous_JJ ,_, there_EX does_VBZ n't_RB lie_VB the_DT singular_JJ path_NN to_TO valor_NN ._. From_IN of_IN old_JJ ,_, it_PRP is_VBZ a_DT sign_NN of_IN strength_NN to_TO fight_VB back_RP a_DT wild_JJ animal_NN ._. It_PRP is_VBZ understandable_JJ if_IN fought_VBN in_IN defense_NN ;_: however_RB ,_, to_TO go_VB the_DT extra_JJ mile_NN and_CC instigate_VB an_DT animal_NN and_CC fight_VB it_PRP is_VBZ the_DT lowest_JJS degree_NN of_IN civilization_NN man_NN can_MD exhibit_VB ._. More_RBR so_RB ,_, in_IN this_DT age_NN of_IN reasoning_NN and_CC knowledge_NN ._. Tradition_NN may_MD call_VB it_PRP ,_, but_CC adhering_JJ blindly_RB to_TO it_PRP is_VBZ idiocy_NN ,_, be_VB it_PRP the_DT famed_JJ Jallikattu_NNP in_IN Tamil_NNP Nadu_NNP -LRB-_-LRB- The_DT Indian_JJ equivalent_NN to_TO the_DT Spanish_JJ Bullfighting_NN -RRB-_-RRB- or_CC the_DT cock-fights_NNS ._. Pelting_VBG stones_NNS at_IN a_DT dog_NN and_CC relishing_VBG it_PRP howl_NN in_IN pain_NN is_VBZ dreadful_JJ ._. If_IN one_CD only_RB gave_VBD as_RB much_JJ as_IN a_DT trickle_VB of_IN thought_NN and_CC conscience_NN the_DT issue_NN would_MD surface_VB as_IN deplorable_JJ in_IN every_DT aspect_NN ._. Animals_NNS play_VBP a_DT part_NN along_IN with_IN us_PRP in_IN our_PRP$ ecosystem_NN ._. And_CC ,_, some_DT animals_NNS are_VBP dearer_RBR :_: the_DT stray_JJ dogs_NNS that_WDT guard_VBP our_PRP$ street_NN ,_, the_DT intelligent_JJ crow_NN ,_, the_DT beast_NN of_IN burden_NN and_CC the_DT everyday_JJ animals_NNS of_IN pasture_NN ._. Literature_NN has_VBZ voiced_VBN in_IN its_PRP$ own_JJ way_NN :_: In_IN The_DT Lord_NN of_IN the_DT Rings_NNP the_DT fellowship_NN treated_VBN Bill_NNP Ferny_NNP 's_POS pony_NN with_IN utmost_JJ care_NN ;_: in_IN Harry_NNP Potter_NNP when_WRB they_PRP did_VBD n't_RB heed_VB Hermione_NNP 's_POS advice_NN on_IN the_DT treatment_NN of_IN house_NN elves_NNS they_PRP learned_VBD the_DT hard_JJ way_NN that_IN it_PRP caused_VBD their_PRP$ own_JJ undoing_NN ;_: and_CC Jack_NNP London_NNP ,_, writes_VBZ all_DT about_IN animals_NNS ._. Indeed_RB ,_, Kindness_NN to_TO animals_NNS is_VBZ a_DT virtue_NN ._. ";

for(String word : str.split("\\s")){

    if(word.split("_").length==2){

        String filteredWord = word.split("_")[0];
        String wordType     = word.split("_")[1];

        System.out.println(word+" = "+filteredWord+ " - "+wordType );

    }

}

И вывод выглядит так:

Man_NN = Man - NN
has_VBZ = has - VBZ
always_RB = always - RB
had_VBN = had - VBN
this_DT = this - DT
notion_NN = notion - NN
that_IN = that - IN
brave_VBP = brave - VBP
deeds_NNS = deeds - NNS
are_VBP = are - VBP
manifest_JJ = manifest - JJ
in_IN = in - IN
physical_JJ = physical - JJ
actions_NNS = actions - NNS
......

почему только n't_RB'разделяется как n't и RB

StringTokenizer stk = new StringTokenizer("n't_RB","_");

while(stk.hasMoreTokens()){
    System.out.println(stk.nextToken());
}

Это будет расщеплено правильно,

n't
RB
Другие вопросы по тегам