在Javascript中检查字符串中的符号

时间:2014-10-13 00:54:08

标签: javascript string

我在coderbyte上遇到问题,问题如下:

  

使用JavaScript语言,使用函数SimpleSymbols(str)   获取传递的str参数并确定它是否为   通过返回字符串truefalse来接受序列。该   str参数将由+=符号组成,并带有多个字母   它们之间(即++d+===+c++==a)和字符串各为true   字母必须用+符号包围。所以左边的字符串   将是false。该字符串不会为空,至少会有   一封信。

我写的代码是:

var SimpleSymbols = function(str){
    var alpha = /[A-Za-z]/;
    var symbolarr = str.split("");
    for(var i = 0; i < symbolarr.length; i++) {
        if(alpha.test(symbolarr[i])) { 
            if(symbolarr[i-1] != "+" & symbolarr[i+1] != "+") {
                return false;
            }
        }
    }   
    return true;
}    

问题在于,当我测试案例SimpleSymbols("+a=")时,我得到true我已经阅读了几次代码并且无法对此进行调试。有人能发现错误吗?

1 个答案:

答案 0 :(得分:2)

调整解决方案

&替换为&&,它们意味着非常不同的东西。

次要评论:您不需要将字符串拆分为数组来访问其字符;您可以使用str[i]直接访问它们。

忽略提到您需要进行范围检查的评论者:arr[-1]将返回undefined,这将不会等同于您所期望的+

Regexp解决方案

测试是否存在给出无效序列的正则表达式。如果它在那里,字符串是非法的。

function SimpleSymbols(str) {
    return !/([^+]|^)[A-Za-z]([^+]|$)/).test(str);
}

英文:

Test for the presence of the following regexp:
    Find any character other than +, or the beginning of the string
    followed by a letter
    followed by any character other than +, or the end of the string
If it is present, return false, else true

状态机方法

考虑编写此类程序的有用方法是作为状态机。我们将使用三种状态:start作为开头,have_plus当我们刚看到加号时,need_plus当我们需要一个加号后面的字母时。

function SimpleSymbols(str) {
    var state = "start";
    var alpha = /[A-Za-z]/;

    for (var i = 0; i < str.length; i++) {
        var type = alpha.test(str[i]) ? 'letter' : str[i] === '+' ? 'plus' : 'other';

        switch (state) {
            case "start":
                switch (type) {
                    case 'letter':                      return false;
                    case 'plus'    state = "have_plus"; break;
                    case 'other':                       break; 
                }
                break;
            case "need_plus":
                switch (type) {
                    case 'letter':                      return false;
                    case 'plus':   state = "have_plus"; break;
                    case 'other':                       return false;
                }
                break;
            case "have_plus":
                switch (type) {
                    case 'letter': state = "need_plus"; break;
                    case 'plus':                        break;
                    case 'other':  state = "start";     break;
                }
                break;
        }

    }
    if (state === "need_plus") return false;
    return true;
}

它会更长一些,但它可能更具可读性和可维护性。但我们可以做得更好。我们将状态逻辑封装在数据结构中,如下所示:

var transitions = {
    start:     {letter: "fail",      plus: "have_plus",   other: "start"},
    need_plus: {letter: "fail",      plus: "have_plus",   other: "fail"},
    have_plus: {letter: "need_plus", plus: "have_plus",   other: "start"},
    fail:      {letter: "fail",      plus: "fail",        other: "fail"}
};

现在我们的程序只运行状态机:

function SimpleSymbols(str) {
    var state = "start",
        alpha = /[A-Za-z]/;

    for (var i = 0; i < str.length; i++) {
        var type = alpha.test(str[i]) ? 'letter' : str[i] === '+' ? 'plus' : 'other';
        state = transitions[state][type];
    }
    return state != "fail";
}

我们可以将它捆绑到状态机对象中:

function stateMachine(state, transitions) {
    return {
        go: function(type) { state = transitions[state][type]; }
        state: function() { return state; }
    };
}

现在我们可以将`SimpleSymbols'写成

function SimpleSymbols(str) {
    var machine = stateMachine("start", transitions),
        alpha = /[A-Za-z]/;

    for (var i = 0; i < str.length; i++) {
        var type = alpha.test(str[i]) ? 'letter' : str[i] === '+' ? 'plus' : 'other';
        machine.go(type);
    }
    return machine.state() != "fail";
}

将标记的分类与运行机器的逻辑分开是很好的做法:

function token_type(c) {
    return /A-Za-z]/.test(str[i]) ? 'letter' : str[i] === '+' ? 'plus' : 'other';
}

然后只是

function SimpleSymbols(str) {
    var machine = stateMachine("start", transitions);
    for (var i = 0; i < str.length; i++) { machine.go(token_type(str[i])); }
    return machine.state() != "fail";
}