Pergunta

var userInput = prompt('enter number here');
var number = new Array(userInput.toString().split(''));
if (number ????){ //checks if the number is in a continuous stream
alert(correct);
}
else{
alert(invalid);
}

In Javascript, what can I do at "????" to check if it is in a continuous order/stream? Also how can I do this so that it only checks for this order/stream after a specific index in the array? Meaning the user enters say "12345678901234" which would pop up correct, but "12347678901234" would pop up invalid?(note there are two 7's) For the second part "3312345678901234" would pop up correct, how can this be implemented?

Foi útil?

Solução

You can make a function that checks any string for a stream of continuous/increasing alpha-numeric characters starting at a given index like this:

function checkContinuous(str, startIndex) {
    startindex = startIndex || 0;
    if (str.length <= startIndex) {
        return false;
    }
    var last = str.charCodeAt(startIndex);
    for (var i = startIndex + 1; i < str.length; i++) {
        ++last;
        if (str.charCodeAt(i) !== last) {
            return false;
        }
    }
    return true;
}

If it's numbers only and wrapping from 9 back to 0 is considered continuous, then it's a little more complicated like this:

function checkContinuous(str, startIndex) {
    // make sure startIndex is set to zero if not passed in
    startIndex = startIndex || 0;
    // skip chars before startIndex
    str = str.substr(startIndex);
    // string must be at least 2 chars long and must be all numbers
    if (str.length < 2 || !/^\d+$/.test(str)) {
        return false;
    }
    // get first char code in string
    var last = str.charCodeAt(0);
    // for the rest of the string, compare to last code
    for (var i = 1; i < str.length; i++) {
        // increment last charCode so we can compare to sequence
        if (last === 57) {
            // if 9, wrap back to 0
            last = 48;
        } else {
           // else just increment
            ++last;
        }
        // if we find one char out of sequence, then it's not continuous so return false
        if (str.charCodeAt(i) !== last) {
            return false;
        }
    }
    // everything was continuous
    return true;
}

Working demo: http://jsfiddle.net/jfriend00/rHH4B/

Outras dicas

No need for arrays, just back though the string one character at a time.

When you hit a 0, substitute 10, and continue until the number is not one more than the previous one.

function continuousFromChar(str, start){
    start= start || 0;
    var i= 0, L= str.length, prev;
    while(L){
        c= +(str.charAt(-- L)) || 10; // use 10 for 0
        prev=+(str.charAt(L- 1));       
        if(c-prev  !== 1) break;
    }
    return  start>=L;
}

var s= "3312345678901234";

continuousFromChar(s,2)

/*  returned value: (Boolean)
true
*/

This will do the checking in real-time entry, but a similar principle could be used to check an entry on a button submit or similar. I was not 100% sure as to which way you wanted it, so I went for the live method.

HTML

<input id="stream" type="text" />

Javascript

window.addEventListener("load", function () {
    document.getElementById("stream").addEventListener("keyup", function (evt) {
        var target = evt.target;
        var value = target.value;
        var prev;
        var last;
        var expect;

        target.value = value.replace(/[^\d]/, "");
        if (value.length > 1) {
            prev = parseInt(value.slice(-2, -1), 10);
            last = parseInt(value.slice(-1), 10);
            expect = prev + 1;

            if (expect > 9) {
                expect = 0;
            }

            if (last !== expect) {
                target.value = value.slice(0, value.length - 1);
            }
        }
    }, false);
});

On jsfiddle

By changing the value here

if (value.length > 1) {

You can change where the checking starts.

Update: Ok, so it is function that you want, and you insist that it splits the string into an array. Then using the above as a reference, you could convert it to something like this.

Javascript

window.addEventListener("load", function () {
    var testStrings = [
        "0123456789012",
        "0123456789",
        "0123455555",
        "555012345678901234",
        "0123455555"];

    function test(string, offset) {
        if (typeof string !== "string" || /[^\d]/.test(string)) {
            return false;
        }

        var array = string.split("");
        var prev;
        var last;
        var expect;

        return !array.some(function (digit, index) {
            if (index >= offset) {
                prev = parseInt(array[index - 1], 10);
                last = parseInt(digit, 10);
                expect = prev + 1;

                if (expect > 9) {
                    expect = 0;
                }

                if (last !== expect) {
                    return true;
                }
            }

            return false;
        });
    }

    testStrings.forEach(function (string) {
        console.log(string, test(string, 1));
    });
});

On jsfiddle

As your question does not fully specify all possibilities, the above will return true for an empty string (""), of course you can simply add a check at the very beginning for that.

I also do not perform any checking for a valid number for your offset, but again this is something simple that you can add.

Of course these are just one (two) of many possible solutions, but hopefully it will set your mind in the right direction of thought.

There are some good answers here, but I would like to show a slight variation. I think it is important to showcase some different aspects of JavaScript and separating interests in code.

  1. Functions as first class objects are cool - the exact rules for "continuous" can be changed with only changing the predicate function. Perhaps we should allow skipping numbers? No problem. Perhaps we allow hex digits? No problem. Just change the appropriate follows function for the specific rules.

  2. This can be implemented generically because strings support indexing. This will work just as well over other array-like objects with an appropriate follows function. Note that there are no string-specific functions used in the continuous function.

Code also on jsfiddle:

// returns true only iff b "follows" a; this can be changed
function follows_1Through9WithWrappingTo0(b,a) {
    if (b === "1" && a === undefined) {
        // start of sequence
        return true;
    } else if (b === "0" && a === "9") {
        // wrap
        return true;
    } else {
        // or whatever
        return (+b) === (+a) + 1;
    }
}

function continuous(seq, accordingTo, from) {
   // strings can be treated like arrays; this code really doesn't care
   // and could work with arbitrary array-like objects
   var i = from || 0;
   if ((seq.length - i) < 1) {
       return true;
   }
   var a = undefined;
   var b = undefined;
   for (; i < seq.length; i++) {
      b = seq[i];
      if (!accordingTo(b, a)) {
         return false; // not continuous
      }
      a = b;
   }
   return true;
}

function assert(label, expr, value) {
    if (!(expr === value)) {
        alert("FAILED: " + label);
    }
}

var follows = follows_1Through9WithWrappingTo0;
assert("empty1", continuous("", follows), true);
assert("empty2", continuous("foobar", follows, 6), true);
assert("skip", continuous("331234", follows, 2), true);
assert("good 1", continuous("123456789", follows), true);
assert("good 2", continuous("12345678901234", follows), true);
assert("bad seq 1", continuous("12347678901234", follows), false);
assert("bad seq 2", continuous("10", follows), false);

// here a different predicate ensures all the elements are the same
var areAllSame = function (b, a) {
                     return a === undefined || a === b;
                 };
assert("same", continuous("aaaaa", areAllSame), true);

Note that the skipping could also be extracted out of the continuous function: in a language with better "functional" collection support, such as C#, this is exactly what I'd do first.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top