Witam, ostatnio pewien post podsunął mi pomysł opracowania wyszukiwania słownikowego. Przy okazji postanowiłem trochę podreperować swój czysty JS. Więc stworzyłem klasę typu słownik która za pomocą bazy słów zgromadzonych wcześniej w pamięci może podpowiadać słowa pasujące do wzorca. Klasa jest prymitywna, nie do końca jestem pewien czy dobrze zaimplementowana - w każdym razie ostatnio jak testowałem to osiągnęła status "nie wiem jak, ale działa". Osobną kwestią pozostaje pytanie o sens stosowania takiego rozwiązania i jego wydajność. Skrypt testowany tylko pod Chrome. Wrzucam i komentujcie (jeśli w ogóle jest co (IMG:
style_emoticons/default/winksmiley.jpg) ).
ADD: Próbowałem wdrożyć się w komentowanie za pomocą JSDoca, ale nie wiem czy dobrze zrozumiałem składnię - dla ułatwienia dodałem na górze skryptu opis tych paru metod
// Obiekt Słownik
// .addWords(words) - dodaje słowa do słownika z tablicy;
// .addWord(word) - dodaje pojedyncze słowo
//
// .searchWord(pattern) - zwraca tablicę słów pasujących do dopasowania
/**
* Tworzy obiekt Słownik
*
* @constructor
* @this {Slownik}
* @param {slownik} przyjmuje sformatowany słownik (np. poprzez ajax)
*/
function Slownik(slownik) {
/** @private */ var dict = (typeof(slownik)!='undefined' && slownik) ? slownik:new Array();
/**
* Podmieniam plik słownika (np. na pobrany za pomocą ajaxa
*
* @this {Slownik}
* @param {new_dict} Nowy słownik
* @return {Slownik} Zwraca referencje do obiektu
*/
this.addDict = function(new_dict) {
dict = new_dict;
return this;
}
/**
* Dodaje słowa do słownika z tablicy
*
* @this {Slownik}
* @param {words} Jednowymiarowa tablica zawierająca słowa
* @return {Slownik} Zwraca referencje do obiektu
*/
this.addWords = function(words) {
ar_length = words.length
for(i in words) {
this.addWord(words[i]);
}
return this;
}
/**
* Dodaje słowo do słownika
*
* @this {Slownik}
* @param {word} Dodawane słowo
* @return {Slownik} Zwraca referencje do obiektu Slownik
*/
this.addWord = function(word) {
var temp_dict = dict;
w_length = word.length;
for (i=0;i<w_length;i++) {
k = word[i]//.charCodeAt(0).toString() - osobna kwestia to kodowanie znaków, nie udało mi się tego rozwiązać
if (!temp_dict[k]) {
temp_dict[k] = (typeof(word[i+1])=='undefined') ? null:new Array();
}
temp_dict = temp_dict[k];
}
return this;
};
/**
* Wyszukuje słowa pasujące do wzorca
*
* @this {Slownik}
* @param {word} Szukany wzorzec
* @return {result} Zwraca tablicę słów pasujących do wzorca
*/
this.searchWord = function(word) {
ref = getIndex(word);
result= new Array();
getMatches(result,ref,word);
return result;
};
function getIndex(word) {
temp_ref = dict;
w_length = word.length;
for (k=0;k<w_length;k++) {
i = word[k]//.charCodeAt(0).toString()
if (temp_ref[i]) {
temp_ref = temp_ref[i];
} else {
return false
}
}
return temp_ref;
};
function getMatches(result,ref,prev_word) {
for(key in ref) {
new_word = prev_word+key//String.fromCharCode(key);
if (ref[key]==null) temp_ref = result.push(new_word);
getMatches(result,ref[key],new_word)
}
};
}
// Przykładowe połączenie z AJAX (używam jQuery)
$(document).ready(function() {
$.get('slownik.php',function(result) {
dictio = new Slownik(result); //tworzę słownik - słowa pobieram za pomocą JSON
res = dictio.searchWord('h'); //zwraca dopasowania do litery h
window.console.debug(res); //wyświetlam w konsoli
},'json')
});
Skrypt do PHP budujący słownik po stronie serwera
class Dictionary {
function __construct($words) {
$this->createDictionary($words);
}
function createDictionary($words) {
foreach($words as $word) {
$this->addWord($word);
}
}
function addWord($word) {
$temp_dict =& $this->dict;
for($i=0;$i<$w_length;$i++) {
$char = $word[$i];
if (!isset($temp_dict[$char])) { $temp_dict[$char] = (isset($word[$i+1
])) ?
array():NULL; }
$temp_dict =& $temp_dict[$char];
}
return $this;
}
function getJSON() {
return json_encode($this->dict);
}
}
// ZASTOSOWANIE
$words = array('hihi','hyhy','humhum'); //przykładowe słowa
$dict = new Dictionary($words); //tworzę słownik
echo $dict->getJSON(); //pobieram słownik zakodowany w formacie JSON