Scvanner
դասը, որը կարելի է կանոնավոր արտահայտությունների միջոցով կարգավորել տեքստից բառեր կարդալու համար։ Բայց այս գրառման մեջ ուզում եմ նաև Java-ի HashMap
բառարանի օգտագործումը համեմատ ել JVM վիրտուալ մեքենայով աշխատող GNU Kawa լեզվի (Scheme լեզվի իրականացում) hashtable
բառարանի օգտագործման հետ։Նախ ներկայացնեմ Java տարբերակը (օգտագործված է JDK 8-ը)։
package wordcount; import java.io.File; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Scanner; /**/ public class WordCount { /**/ private static void readFile( String name, HashMap<String,Integer> words ) { // տրված անունով ֆայլի համար ստեղծել Scanner օբյեկտ try( Scanner scan = new Scanner(new File(name)) ) { // բացի մեծատառերից ու փոքրատառերից ամեն ինչ համարել բաժանիչ scan.useDelimiter( "[^A-Za-z]+" ); // քանի դեռ Scanner-ից կարելի է կարդալ while( scan.hasNext() ) { // կարդալ հերթական բառը String wo = scan.next().toLowerCase(); // գտնել կարդացած բառի արտապատկերումը բառարանում Integer co = words.get(wo); // եթե այդ բառը բառարանում չկա, ավելացնել այն՝ 1 քանակով, // իսկ եթե կա՝ քանակն ավելացնել 1-ով words.put(wo, co == null ? 1 : co + 1); } } catch( FileNotFoundException ex ) { System.err.println(ex.getMessage()); } } /**/ public static void main(String[] args) { // ստեղծել String->Integer արտապատկերում HashMap<String,Integer> words = new HashMap<>(); // կարդալ ֆայլի պարունակությունը words բառարանի մեջ readFile("~/Projects/martineden.txt", words); // բառ-քանակ զույգերն արտածել ստանդարտ արտածման հոսքին words.forEach( (k,v) -> System.out.printf("%s\t%s\n", k, v) ); } }
Հիմա ցույց տամ, թե ինչպես եմ Kawa լեզվի միջոցներով կարդում ֆայլի բառերի հաջորդականությունը և կազմում դրանց հաճախությունների բառարանը։ Նախ սահմանեմ
read-all-words
ֆունկցիան, որն արգումենտում ստանում է Java լեզվի Scanner
օբյեկտը և վերագարձնում է տեքստի բառերի հաճախությունների բառարանը՝ որպես Scheme լեզվի hashtable
օբյեկտ։
(define (read-all-words sca :: Scanner) (define (read-all-words-rec ht) (when (invoke sca 'hasNext) (add-to-table (string-downcase (invoke sca 'next)) ht) (read-all-words-rec ht))) (let ((words (make-hashtable string-hash string=?))) (read-all-words-rec words) words))
read-all-words
ֆունկցիայի համար սահմանված է read-all-words-rec
լոկալ ռեկուրսիվ ֆունկցիան, որը Scanner
օբյեկտից կարդում է մեկ բառ, այդ բառի բոլոր մեծատառերը դարձնում է փոքրատառ՝ string-downcase
ֆունկցիայով, ապա ավելացնում է արգումենտում տրված բառարանում։ Բառարանը ստեղծվում է որպես read-all-words
ֆունկցիայի լոկալ օբյեկտ՝ make-hashtable
ֆունկցիայով։ Բառը բառարանում ավելացնող add-to-table
ֆունկցիան սահմանված է հետևյալ կերպ․
(define (add-to-table w table) (let ((co (hashtable-ref table w 0))) (hashtable-set! table w (+ co 1))))
read-file
ֆունկցիան, որ կսահմանեմ ստորև, տրված ֆայլի անունի համար ստեղծում է մի Scanner
օբյեկտ և "[^A-Za-z]+"
արտահայտությունը սահմանում է որպես դրա բաժանիչ։ Հետո read-all-words
ֆունկցիայով ստանում է բառերի հաճախությունների բառարանը, այդ բառարանից կազմում է կետով զույգերի (dotted pair) ցուցակ, և վերադարձնում է այդ վերջին ցուցակն՝ ըստ բառերի այբբենական կարգի կարգավորած։
(define (read-file name ::) (let ((sca (Scanner:new (File:new name)))) (invoke sca 'useDelimiter "[^A-Za-z]+") (let-values (((ks vs) (hashtable-entries (read-all-words sca)))) (invoke sca 'close) (list-sort (lambda (a b) (stringlist ks) (vector->list vs))))))
No comments:
Post a Comment