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