Autocomplete using a trie

后端 未结 2 2010
被撕碎了的回忆
被撕碎了的回忆 2020-12-07 18:02

I am working on an autocompletion script and was thinking about using a trie. My problem is I want everything that matches to be returned. So for example I type in the let

相关标签:
2条回答
  • 2020-12-07 18:37

    You can absolutely do it using a trie. Here is some code I threw together that can point you in the right direction:

    var tokenTree = function (tokenArray) {
      var createLetterObject = function (l) {
        var pChildren = [];
    
        var getMatchingWords = function (characterArr, availableWords, children) {
            if (characterArr.length === 0) {
                for (var child in children) {
                    if ({}.hasOwnProperty.call(children, child)) {
                        var currentChild = children[child];
    
                        var words = currentChild.getWords(characterArr);
    
                        for (var pos in words) {
                            if ({}.hasOwnProperty.call(words, pos)) {
                                availableWords.push(words[pos]);
                            }
                        }
    
                        if (currentChild.word) {
                            availableWords.push(currentChild.word);
                        }
                    }
                }
            } else {
                var currentCharacter = characterArr.pop();
                getMatchingWords(characterArr, availableWords, children[currentCharacter].children);
            }
        };
    
        function doGetWords(wordPart) {
            var len = wordPart.length;
            var ar = [];
            var wordList = [];
    
            for (var ii = len - 1; ii >= 0; ii --) {
                ar.push(wordPart[ii].toUpperCase());
            }
    
            getMatchingWords(ar, wordList, pChildren);
    
            return wordList;
        }
    
        return {
            letter: l,
            children: pChildren,
            parent: null,
            word: null,
            getWords: doGetWords
        };
    };
    
    var startingPoint = createLetterObject();
    
    function parseWord(wordCharacterArray, parent, fullWord) {
        if (wordCharacterArray.length === 0) {
            parent.word = fullWord;
            return;
        }
    
        var currentCharacter = wordCharacterArray.pop().toUpperCase();
    
        if (!parent.children[currentCharacter]) {
            parent.children[currentCharacter] = createLetterObject(currentCharacter);
        }
    
        parseWord(wordCharacterArray, parent.children[currentCharacter], fullWord);
    }
    
    for (var counter in tokenArray) {
        if ({}.hasOwnProperty.call(tokenArray, counter)) {
            var word = tokenArray[counter];
    
            if (!word) {
                continue;
            }
    
            var ar = [];
    
            var wordLength = word.length;
    
            for (var ii = wordLength - 1; ii >= 0; ii--) {
                ar.push(word[ii]);
            }
    
            parseWord(ar, startingPoint, word);
        }
    }
    
      return startingPoint;
    };
    

    Usage

    var tokens = ["Token", "words", "whohaa", "mommy", "test", "wicked"];
    var tree = tokenTree(tokens);
    var currentTokenSet = 'w'; 
    var list = tree.getWords(currentTokenSet);
    
    // it will return words,whohaa,wicked.
    console.log(list) 
    

    I'm not saying this is anywhere near the best or most efficient way, but it should at least get you pointed in the right direction.

    Here is a jsfiddle showing it working: https://jsfiddle.net/es6xp8h9/

    0 讨论(0)
  • 2020-12-07 18:44

    Regarding the time to discover items at a root note, if you're doing this for an autocomplete, it's likely you won't be returning too many results per 'match'. If you wanted to trade off space for speed, you could store references to the 'top n' items at each of the nodes. This, of course, would require more time on update

    0 讨论(0)
提交回复
热议问题