Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/440.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何读取这个基数树结构来确定下一个字符串的概率?_Javascript_Patricia Trie - Fatal编程技术网

Javascript 如何读取这个基数树结构来确定下一个字符串的概率?

Javascript 如何读取这个基数树结构来确定下一个字符串的概率?,javascript,patricia-trie,Javascript,Patricia Trie,在JavaScript中,我尝试接受给定的用户输入,并猜测可能完成用户当前(不完整)键入的单词的3个最可能的单词。猜测基于用户过去的输入。我正在做这个 我构建的用于记录用户过去输入的结构是经过修改的: 输入:“嘿” 这个数据结构构建得非常完美,我认为它是实现上述目标的最佳结构。我的问题是读取基数树数据以定义给定输入的3个最可能的单词的函数。例如,在上述数据中,如果用户输入“h”,猜测函数应返回如下对象: guess : { 1 : "hey", 2 : "", 3 : "" }

在JavaScript中,我尝试接受给定的用户输入,并猜测可能完成用户当前(不完整)键入的单词的3个最可能的单词。猜测基于用户过去的输入。我正在做这个

我构建的用于记录用户过去输入的结构是经过修改的:

输入:“

这个数据结构构建得非常完美,我认为它是实现上述目标的最佳结构。我的问题是读取基数树数据以定义给定输入的3个最可能的单词的函数。例如,在上述数据中,如果用户输入“
h
”,猜测函数应返回如下对象:

guess : {
   1 : "hey",
   2 : "",
   3 : ""
}
下面是我的代码/进度:

学习-获取完成的输入字符串,并将组合组织到基数树中(
brain
):

没关系。不幸的是,下一个用于读取数据并猜测用户正在键入的单词的代码并不好。对我来说,这是一个非常复杂的函数。我把它分成了几个小函数,据我所知,这是最好的做法,但我担心我弄糟了,可能会简单得多:

猜测-获取“习得”字符串数据,并对用户可能键入的单词进行3次猜测:

function guess(progress, brain) {
    console.log("Guessing based on: " + progress);
    var guesses = {
        0: "",
        1: "",
        2: ""
    }
    var firstChar = progress[0]; 
    if (brain[firstChar]) {
        var step = brain[firstChar];
        for (var i = 0; i < progress.length; i++) {
            var char = progress[i];
            if (step.followables[char]) {
                step = step.followables[char];
                if (i == progress.length) {
                    var guesses = nextStrings(step.followables);
                    renderGuesses(guesses);
                }
            } else {
                renderGuesses(guesses);
            }
        }
    } else {
        renderGuesses(guesses);
    }
}

function renderGuesses(guesses) {
    console.log(guesses);
    $('#guess-1').text(guesses[0]);
    $('#guess-2').text(guesses[1]);
    $('#guess-3').text(guesses[2]);
}

function nextStrings(followables) {
    console.log('Searching for next string...');
    var results;
    if (followables.length > 0) {
        results = chooseRoutes(followables);
    } else {
        results = {
            0: "",
            1: "",
            2: ""
        }
    }
    console.log(result);
    return result;
}

function chooseRoutes(followables) {
    var results = {
        0: {
            value: "",
            count: 0
        },
        1: {
            value: "",
            count: 0
        },
        2: {
            value: "",
            count: 0
        }
    };
    for (var i = 0; i < followables.length; i++) {
        var count = followables[i].count;
        if (count > results[0].count) {
            results[0].value = followStr(followables[i], "");
        } else if (count > results[1].count) {
            results[1].value = followStr(followables[i], "");
        } else if (count > results[2].count) {
            results[2].value = followStr(followables[i], "");
        }
    }
    console.log(results);
    return results;
}

function followStr(followables, str) {
    var guess = {
        value: "",
        count: 0
    };
    for (var i = 0; i < followables.length; i++) {
        if (followables[i].count > guess.count) {
            guess = followables[i];
        }
    }
    followables = guess.followables;
    if (guess.value != " ") {
        str += guess;
        followStr(followables, str);
    } else {
        console.log(str);
        return str;
    }
}
功能猜测(进展,大脑){
log(“基于:+进度的猜测”);
var猜测={
0: "",
1: "",
2: ""
}
var firstChar=progress[0];
if(brain[firstChar]){
var step=大脑[firstChar];
对于(变量i=0;i0){
结果=选择结果(如下表);
}否则{
结果={
0: "",
1: "",
2: ""
}
}
控制台日志(结果);
返回结果;
}
函数选择器输出(以下选项){
风险值结果={
0: {
值:“”,
计数:0
},
1: {
值:“”,
计数:0
},
2: {
值:“”,
计数:0
}
};
for(var i=0;i结果[0]。计数){
结果[0].value=followStr(followstables[i],“”);
}else if(计数>结果[1]。计数){
结果[1],值=followStr(followstables[i],“”);
}否则如果(计数>结果[2]。计数){
结果[2],值=followStr(followstables[i],“”);
}
}
控制台日志(结果);
返回结果;
}
函数followStr(followsables,str){
var猜测={
值:“”,
计数:0
};
for(var i=0;iguess.count){
猜测=可遵循的;
}
}
followables=guess.followables;
如果(guess.value!=“”){
str+=猜测;
followStr(followstables,str);
}否则{
console.log(str);
返回str;
}
}


侧注-虽然在字典上进行模糊字符串搜索是一种更常见的方法,但学习方法是一种根据用户的写作/消息传递风格定制猜测并支持用户非标准词汇表的好方法(“
heyy
”、“
sup
”、“
:p
”、“
lol
”)-这些猜测的结果可以与标准词典结果相结合(并优先于标准词典结果)。

用于词典的结构不正确,它应该包含对象数组。例如,输入以下文字后:

hi
hi
hi
hi
hi
hey
hello
hella
结构应为:

history: [{
    letter: "h",
    count: 8,
    followables: [{
        letter: "e",
        count: 3,
        followables: [{
            letter: "y",
            count: 1,
            followables: []
        }, {
            letter: "l",
            count: 2,
            followables: [{
                letter: "l",
                count: 2,
                followables: [{
                    letter: "o",
                    count: 1,
                    followables: []
                }, {
                    letter: "a",
                    count: 1,
                    followables: []
                }]
            }]
        }]
    }, {
        letter: "i",
        count: 5,
        followables: []
    }]
}]
您创建和存储历史记录的方式(我将使用localStorage)对我不感兴趣。重点放在递归函数上,这些函数深入到树的内部以获取建议。这一个获得给定单词的最终
可遵循项

findChildren: function (node, depth) {
    /* Traverse history for current word, there is only one path */
    for (k in node) {
        if (node[k].letter == app.progress[depth]) {
            if (depth + 1 == app.progress.length) {
                /* Found it, hope it has followables */
                return node[k].followables;
            } else {
                /* Must go deeper... */
                return app.findChildren(node[k].followables, depth + 1);
            };
        };
    };
    /* No results */
    return false;
}
第二个(getWord)创建建议:

countWordsFromNode: function (node) {
    for (i in node) {
        if (node[i].followables.length) {
            app.countWordsFromNode(node[i].followables);
        } else {
            app.totalInNode++;
        };
    };
},
getWord: function (node, limit) {
    /* First sort by count */
    var sorted = node.sort(function (n1, n2) {
        return n2.count - n1.count;
    });
    for (k in sorted) {
        app.guesses[app.totalFound].word += sorted[k].letter;
        if (sorted[k].followables.length) {
            app.totalInNode = 0;
            app.countWordsFromNode(sorted[k].followables);
            for (m = 1; m < app.totalInNode; m++) {
                if ((app.totalFound + m) < limit) {
                    app.guesses[app.totalFound + m].word += sorted[k].letter;
                };
            };
            app.getWord(sorted[k].followables, limit);
        } else {
            /* End of word */
            app.totalFound++;
        };
        if (app.totalFound >= limit) {
            /* Found all suggestions */
            break;
        };
    };
}
编辑:
修正了在右边添加字母的错误。

抛开主观因素不谈,实际上我对自己无法构建这个
guess
函数感到有点沮丧。功能/总体目标实际是高级/困难的,还是我需要更多的练习?在过去的2-3年的高中生活中,我一直在学习JS,我很想知道现在我是否能够轻松地完成类似的事情……这不是一个特别容易实现的算法,但看看你可能会发现,如果你有一个匹配的单词数据库,那么你可能会发现它更容易实现。@Qantas949当然,我可能希望在生产实现中结合使用基于字典的典型模糊字符串搜索。我在这里的目的是关注用户的输入,它擅长猜测常见但不正确的字符串,如“u”、“:P”,“嗯,您的示例树不是实际的trie,它不是压缩的?那
.count
到底代表了什么?@Bergi也许不是-我没有太多地研究trie背后的基本思想,但它的结构像一个,遵循相同的思想,减去,也许,你所说的压缩。和
计数
表示
findChildren: function (node, depth) {
    /* Traverse history for current word, there is only one path */
    for (k in node) {
        if (node[k].letter == app.progress[depth]) {
            if (depth + 1 == app.progress.length) {
                /* Found it, hope it has followables */
                return node[k].followables;
            } else {
                /* Must go deeper... */
                return app.findChildren(node[k].followables, depth + 1);
            };
        };
    };
    /* No results */
    return false;
}
countWordsFromNode: function (node) {
    for (i in node) {
        if (node[i].followables.length) {
            app.countWordsFromNode(node[i].followables);
        } else {
            app.totalInNode++;
        };
    };
},
getWord: function (node, limit) {
    /* First sort by count */
    var sorted = node.sort(function (n1, n2) {
        return n2.count - n1.count;
    });
    for (k in sorted) {
        app.guesses[app.totalFound].word += sorted[k].letter;
        if (sorted[k].followables.length) {
            app.totalInNode = 0;
            app.countWordsFromNode(sorted[k].followables);
            for (m = 1; m < app.totalInNode; m++) {
                if ((app.totalFound + m) < limit) {
                    app.guesses[app.totalFound + m].word += sorted[k].letter;
                };
            };
            app.getWord(sorted[k].followables, limit);
        } else {
            /* End of word */
            app.totalFound++;
        };
        if (app.totalFound >= limit) {
            /* Found all suggestions */
            break;
        };
    };
}
guesses: [
    {
        element: $('#guess-1'),
        word: ''
    },
    {
        element: $('#guess-2'),
        word: ''
    },
    {
        element: $('#guess-3'),
        word: ''
    }
]