【问题标题】:Autocomplete using a trie使用 trie 自动完成
【发布时间】:2011-06-28 17:33:47
【问题描述】:

我正在编写一个自动完成脚本,并且正在考虑使用 trie。我的问题是我希望返回所有匹配的内容。例如,我输入字母r 我希望返回所有以r 开头的条目。然后所有以re 等开头的条目。这是否可行,以及它如何工作。另外,如果有更好的方法,我愿意接受建议。我问的原因是,从r 分支返回所有节点似乎会很复杂并且需要进行大量处理。

是的,我可能正在重新发明轮子,但我想了解它是如何工作的。

【问题讨论】:

    标签: javascript algorithm trie


    【解决方案1】:

    你完全可以使用 trie 来做到这一点。这是我整理的一些代码,可以为您指明正确的方向:

    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;
    };
    

    用法

    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) 
    

    我并不是说这是最好或最有效的方法,但它至少应该让你指向正确的方向。

    这是一个 jsfiddle 显示它的工作原理:https://jsfiddle.net/es6xp8h9/

    【讨论】:

    • 为什么要使用 CharacterArr 而不是您声明的 CharacterArray? :)
    【解决方案2】:

    关于在根注释中发现项目的时间,如果您这样做是为了自动完成,那么每次“匹配”可能不会返回太多结果。如果您想以空间换取速度,您可以在每个节点上存储对“前 n”项的引用。当然,这将需要更多时间进行更新

    【讨论】:

      猜你喜欢
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 2014-05-31
      相关资源
      最近更新 更多