コーヒー「JavaSE8」を使用した英語テキストの分析



著者から



「あらゆる好奇心が導く」-この物語が始まったのはこれらの言葉でした。



これは事実でした。



私はアメリカからの出張から帰国しました。そこで、私は一ヶ月を過ごしました。 英語で徹底的かつきちんと学習しましたが、問題はありません。海外の友人のところに来たとき、まったく理解していないことに気付きました。 私の悔しさには限界がありませんでした。 最初に到着したとき、私は流な英語を話す友人に会い、彼の魂を注ぎ出しました。 ..」



うーん、そうですか、私の頭の中に疑問が生じました...そして、話されたテキストを分析し、いわば使用された言葉を決定するという考えが頭に浮かびました。



ソースデータ



口語的なテキストとして、私はシリーズFriendsのシリーズのスクリプトを取り上げることに決めました。同時に、仮説をテストします-「...シリーズを英語で見れば、あなたはしっかりと舌を引き締めます...」



使用技術





期待される結果



作業の結果はjarライブラリーになります。これは、一定の理解率を持つテキストの語彙の最小値になります。 つまり、たとえば、テキスト全体とライブラリについて80%を理解したいのです。テキストを分析すると、このために学習する必要がある一連の単語が得られます。



それでは、行きましょう。



DTOオブジェクト(戦闘ユニット)



ReceivedText.java


package ru.lexmin.lexm_core.dto; /** *           (text) *    (percent) * */ public class ReceivedText { /** *  */ private static final long serialVersionUID = 5716001583591230233L; // ,    private String text; //      private int percent; /** *   */ public ReceivedText() { super(); } /** *    * * @param text * {@link String} * @param percent * int */ public ReceivedText(String text, int percent) { super(); this.text = text; this.percent = percent; } /** * @return text {@link String} */ public String getText() { return text; } /** *   * * @param text * text {@link String} */ public void setText(String text) { this.text = text; } /** * @return percent {@link int} */ public int getPercent() { return percent; } /** *   * * @param percent * percent {@link int} */ public void setPercent(int percent) { this.percent = percent; } }
      
      





Wordstat.java


 package ru.lexmin.lexm_core.dto; import java.util.HashMap; import java.util.Map; /** *        : -    *  -    . * *      countOfWords (int)   *    frequencyWords (Map<String, Integer>): -   *  -      * *  receivedText -    dto     . * */ public class WordStat { /** *  */ private static final long serialVersionUID = -1211530860332682161L; //   dto      private ReceivedText receivedText; // -   ,    receivedText private int countOfWords; //     ,    receivedText, //      private Map<String, Integer> frequencyWords; /** *    */ public WordStat() { super(); } /** *    * * @param receivedText * @param countOfWords * @param frequencyWords */ public WordStat(ReceivedText receivedText, int countOfWords, Map<String, Integer> frequencyWords) { this.receivedText = receivedText; this.countOfWords = countOfWords; this.frequencyWords = frequencyWords; } /** *     receivedText   . *       * * @param receivedText */ public WordStat(ReceivedText receivedText) { this.receivedText = receivedText; //       this.countOfWords = 0; this.frequencyWords = new HashMap<String, Integer>(); } /** * @return receivedText {@link ReceivedText} */ public ReceivedText getReceivedText() { return receivedText; } /** *   * * @param receivedText * receivedText {@link ReceivedText} */ public void setReceivedText(ReceivedText receivedText) { this.receivedText = receivedText; } /** * @return countOfWords {@link int} */ public int getCountOfWords() { return countOfWords; } /** *   * * @param countOfWords * countOfWords {@link int} */ public void setCountOfWords(int countOfWords) { this.countOfWords = countOfWords; } /** * @return frequencyWords {@link Map<String,Integer>} */ public Map<String, Integer> getFrequencyWords() { return frequencyWords; } /** *   * * @param frequencyWords * frequencyWords {@link Map<String,Integer>} */ public void setFrequencyWords(Map<String, Integer> frequencyWords) { this.frequencyWords = frequencyWords; } }
      
      







まあ、すべてがシンプルで明確です、コードに十分なコメントがあると思います



テキストアナラ​​イザーインターフェイス(機能の定義)



TextAnalyzer.java


 package ru.lexmin.lexm_core; import ru.lexmin.lexm_core.dto.ReceivedText; import ru.lexmin.lexm_core.dto.WordStat; /** *         *   * */ public interface TextAnalyzer { /** *     {@link WordStat},  , *     {@link ReceivedText} * * @param receivedText * {@link ReceivedText} * @return   {@link WordStat} */ public abstract WordStat getWordStat(ReceivedText receivedText); }
      
      







WordStat(DTO)から返される外部メソッドは1つだけで十分であり、そこから単語を抽出します。



テキストアナラ​​イザーの実装



TextAnalyzerImp.java


 package ru.lexmin.lexm_core; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; import ru.lexmin.lexm_core.dto.ReceivedText; import ru.lexmin.lexm_core.dto.WordStat; /** *      TextAnalyzer * */ public class TextAnalyzerImp implements TextAnalyzer { /*  */ private final int PERCENT_100 = 100; private final int ONE_WORD = 1; private final String SPACE = " "; //  :    private final String ANY_APOSTROPHE = "[']"; // ,   private final String AVAILABLE_APOSTROPHE = "'"; //  :    ,     // (') private final String ONLY_LATIN_CHARACTERS = "[^az\\s']"; //  : ,    private final String SPACES_MORE_ONE = "\\s{2,}"; /** *       ,  *  .      ,  *    .       . * * @param text * {@link String} * @return   */ private String filterText(String text) { String resultText = text.toLowerCase().replaceAll(ANY_APOSTROPHE, AVAILABLE_APOSTROPHE) .replaceAll(ONLY_LATIN_CHARACTERS, SPACE).replaceAll(SPACES_MORE_ONE, SPACE); return resultText; } /** *      Map<{}, {}> * * @param text * {@link String} * @return  Map */ private Map<String, Integer> getWordsMap(String text) { Map<String, Integer> wordsMap = new HashMap<String, Integer>(); String newWord = ""; Pattern patternWord = Pattern.compile("(?<word>[a-z']+)"); Matcher matcherWord = patternWord.matcher(text); //       while (matcherWord.find()) { newWord = matcherWord.group("word"); if (wordsMap.containsKey(newWord)) { //      Map      1 wordsMap.replace(newWord, wordsMap.get(newWord) + ONE_WORD); } else { //    Map       1 wordsMap.put(newWord, ONE_WORD); } } return wordsMap; } /** *     ,    *    Map * * @param wordsMap * {@link Map} * @return     ,    Map */ private int getCountOfWords(Map<String, Integer> wordsMap) { int countOfWords = 0; //          Map for (Integer value : wordsMap.values()) countOfWords += value; return countOfWords; } /** *       * numberXPercents   number100Percents * * @param number100Percents * int * @param numberXPercents * int * @return   */ private int getPercent(int number100Percents, int numberXPercents) { return (numberXPercents * PERCENT_100) / number100Percents; } /** *      ,     *     * * @param wordsMap * {@link Map} * @param countOfWords * int * @param percent * int * @return   ,   *    */ private Map<String, Integer> filterWordsMap(Map<String, Integer> wordsMap, int countOfWords, int percent) { // LinkedHashMap -  ,    //   Map<String, Integer> resultMap = new LinkedHashMap<String, Integer>(); int sumPercentOfWords = 0; //    Map   Entry<String, Integer>, //    Stream<Entry<String, Integer>> streamWords = wordsMap.entrySet() .stream().sorted(Map.Entry.comparingByValue( (Integer value1, Integer value2) -> ( value1.equals(value2)) ? 0 : ((value1 < value2) ? 1 : -1) ) ); //        Iterator<Entry<String, Integer>> iterator = streamWords.iterator(); //   resultMap     ,   //      while (iterator.hasNext() && (sumPercentOfWords < percent)) { Entry<String, Integer> wordEntry = iterator.next(); resultMap.put(wordEntry.getKey(), wordEntry.getValue()); sumPercentOfWords += getPercent(countOfWords, wordEntry.getValue()); } return resultMap; } /* * (non-Javadoc) * * @see * ru.lexmin.lexm_core.TextAnalyzer#getWordStat(ru.lexmin.lexm_core.dto. * ReceivedText) */ @Override public WordStat getWordStat(ReceivedText receivedText) { WordStat wordStat = new WordStat(receivedText); Map<String, Integer> wordsMap = getWordsMap(filterText(receivedText.getText())); wordStat.setCountOfWords(getCountOfWords(wordsMap)); wordStat.setFrequencyWords( filterWordsMap(wordsMap, wordStat.getCountOfWords(), receivedText.getPercent()) ); return wordStat; } }
      
      





私はすべての方法について可能な限りコメントしようとしました。



要するに、次のことが起こります。

最初に、ラテン文字、アポストロフィ、またはスペースにあるすべてのものがテキストから切り取られます。 行内の2を超えるスペースの数は1に置き換えられます。 これは、メソッドmethod filterText(String text)で行われます



さらに、準備されたテキストから単語の配列が形成されます-マップ<単語、テキスト内の番号>。 getWordsMap(String text)メソッドがこれを担当します



getCountOfWordsメソッド(Map <String、Integer> wordsMap)を使用して単語の総数を数えます



最後に、 filterWordsMapメソッド(Map <String、Integer> wordsMap、int countOfWords、int percent)でテキストのN%をカバーするために必要な単語をフィルター処理します



実験を行います(コンソールに単語のリストを表示します)



 package testText; import ru.lexmin.lexm_core.TextAnalyzer; import ru.lexmin.lexm_core.TextAnalyzerImp; import ru.lexmin.lexm_core.dto.ReceivedText; import ru.lexmin.lexm_core.dto.WordStat; public class Main { public static void main(String[] args) { final int PERCENT = 80; TextAnalyzer ta = new TextAnalyzerImp(); String friends = "There's nothing to tell! He's ....      "; ReceivedText receivedText = new ReceivedText(friends, PERCENT); WordStat wordStat = ta.getWordStat(receivedText); System.out.println("   : " + wordStat.getCountOfWords()); System.out.println(" ,  80% : " + wordStat.getFrequencyWords().size()); System.out.println(" ,  80% "); wordStat.getFrequencyWords().forEach((word, count) -> System.out.println(word)); } }
      
      







結果



テキスト内の単語数: 1481

テキストの80%をカバーする単語数: 501

テキストの80%をカバーする単語のリスト: i、a、and、you、the、to、just、this、it、be、is、my、no、of、that、me、do n't、with、it's、out、ポール、あなた、持っている、彼女、大丈夫、 ...など



おわりに



この実験では、最初のシーズンの2つのエピソードのみを分析し、結論を出すには早すぎますが、2つのエピソードは約80-90分続き、理解に必要なのは501単語だけで十分です(残りの20%は考え抜かれ、論理的および視覚的知覚)。



PS:私自身から、私の友人はこの実験に興味を持っていたと言いたいです、そして、我々はこの話題を発展させます。 誰でも興味のあるテキストを分析できるポータルの作成を開始することが決定されました。 このような分析の結果に基づいて、統計が収集され、英単語のTORが形成されます。



以下の投稿では、この厄介な道に関するすべての問題と成果について書いていきます。 ご清聴ありがとうございました。またお会いしましょう。



All Articles