Increment a string with letters?

前端 未结 12 1293
礼貌的吻别
礼貌的吻别 2021-02-08 12:35

I need to increment a string from.. let\'s say aaa to zzz and write every incrementation in the console (is incrementation even a word?). It would go s

相关标签:
12条回答
  • 2021-02-08 13:11

    Assuming you will always have 3 letters (or any other set number of letters), off the top of my head I would think to:

    Have separate variables for each letter, so instead of:

    string = "aaa";
    

    Have:

    string1 = "a";
    string2 = "a";
    string3 = "a";
    

    Then increment the one you need at each iteration. This will take a little trial and error probably, and looks like you're going from the right over to the left, so roughly:

    if(string3 != "z"){
        // Increment string 3 by a letter
    }else if(string2 != "z"){
        // Increment string 2 by a letter
    }else if (string1 != "z"){
        // Increment string 1 by a letter
    }else{
        // What ever you want to do if "zzz"
    }
    

    I didn't test that but it would be something close.

    Then

    string = string1 + string2+ string3
    

    Now you are left with a single variable like before which you can do what you intended with (i.e. output etc.)

    You could also do this with a string array, which would make it easier to have a changing amount of letters, and would need a little more code to count the array length and stuff, but I'd want to get it working at least statically first like above.

    0 讨论(0)
  • 2021-02-08 13:13

    I took a different approach with this, using a permutations function which recursively generated all the possible permutations one could generate using characters from an array repeated n times. The code looks like this.

    //recursively generates permutations
    var permutations = function (li, rep) {
        var i, j, next, ret = [];
        // base cases
        if (rep === 1) {
            return li;
        }
        if (rep <= 0) {
            return [];
        }
        // non-base case
        for (i = 0; i < li.length; i += 1) {
            // generate the next deepest permutation and add
            // the possible beginnings to those
            next = permutations(li, rep-1);
            for (j = 0; j < next.length; j += 1) {
                ret.push(li[i] + next[j]);
            }
        }
        return ret;
    };
    
    // returns an array of numbers from [start, end)
    // range(10, 14) -> [10, 11, 12, 13]
    var range = function (start, end) {
        var i, ret = [];
        for (i = start; i < end; i+= 1) {
            ret.push(i);
        }
        return ret;
    };
    
    // generates letters ('abcd...')
    var letters = String.fromCharCode.apply(this, range('a'.charCodeAt(0), 'z'.charCodeAt(0)+1));
    
    // calls the function itself, and .join's it into a string
    document.body.innerHTML = (permutations(letters, 3)).join(' ');

    0 讨论(0)
  • 2021-02-08 13:13

    Let's try this approach. It's a straight loop which produces the complete sequence from aaa,aab,aac,.....,xzz,yzz,zzz

    function printSeq(seq){
        console.log(seq.map(String.fromCharCode).join(''));
    }
    
    
    var sequences = [];
    
    (function runSequence(){
        var seq = 'aaa'.split('').map(function(s){return s.charCodeAt(0)});
        var stopCode = 'z'.charCodeAt(0);
        do{
            printSeq(seq);
            sequences.push(seq.map(String.fromCharCode).join(''));
            if (seq[2]!=stopCode) seq[2]++;
            else if (seq[1]!=stopCode) seq[1]++;
            else if (seq[0]!=stopCode) seq[0]++;
        }while (seq[0]<stopCode);
        printSeq(seq);
        sequences.push(seq.map(String.fromCharCode).join(''));
    })();

    The results are displayed in the console and also you'll get a complete sequence stored in sequence array. Hope this is readable and helpful.

    0 讨论(0)
  • 2021-02-08 13:14

    I used your code and added a few new functions.

    String.prototype.replaceAt = function(index, character) {
        return this.substr(0, index) + character + this.substr(index+character.length);
    }
    
    String.prototype.incrementAt = function(index) {
        var newChar = String.fromCharCode(this.charCodeAt(index) + 1); // Get the next letter that this char will be
        if (newChar == "{") { // If it overflows
            return this.incrementAt(index - 1).replaceAt(index, "a"); // Then, increment the next character and replace current char with 'a'
        }
        return this.replaceAt(index, newChar); // Replace this char with next letter
    }
    
    String.prototype.increment = function() {
        return this.incrementAt(this.length - 1); // Starts the recursive function from the right
    }
    
    console.log("aaa".increment()); // Logs "aab"
    console.log("aaz".increment()); // Logs "aba"
    console.log("aba".increment()); // Logs "abb"
    console.log("azz".increment()); // Logs "baa"
    

    This incrementAt function is recursive and increments the character it is currently on. If in the process it overflows (the character becomes { which is after z) it calls incrementAt on the letter before the one it is on.

    The one problem with this code is if you try to increment zzz you get aaaz. This is because it is trying to increment the -1th character which is the last one. If I get time later I'll update my answer with a fix.

    Note that this solution will work if you have a different length string to start off. For example, "aaaa" will count up to "zzzz" just fine.

    0 讨论(0)
  • 2021-02-08 13:15

    This function gives 3 characters based on a number:

    function n2s (n) {
        var s = '';
        while (s.length < 3) {
            s = String.fromCharCode(97 + n % 26) + s;
            n = Math.floor(n / 26);
        }
        return s;
    }
    

    To print strings from "aaa" to "zzz":

    var zzz = Math.pow(26, 3) - 1;
    for (var n = 0; n <= zzz; n++) {
        console.log(n2s(n));
    }
    

    function n2s (n) {
        var s = '';
        while (s.length < 3) {
            s = String.fromCharCode(97 + n % 26) + s;
            n = Math.floor(n / 26);
        }
        return s;
    }
    
    var result = [];
    var zzz = Math.pow(26, 3) - 1;
    for (var n = 0; n <= zzz; n++) {
        result.push(n2s(n));
    }
    document.body.innerHTML = result.join(' ');

    Ask for details :-)


    Improvements

    Performances compared to the accepted answer: http://jsperf.com/10-to-26.

    // string to number: s2n("ba") -> 26
    function s2n(s) {
        var pow, n = 0, i = 0;
        while (i++ < s.length) {
            pow = Math.pow(26, s.length - i);
            n += (s.charCodeAt(i - 1) - 97) * pow;
        }
        return n;
    }
    
    // number to string: n2s(26) -> "ba"
    function n2s(n) {
        var s = '';
        if (!n) s = 'a'; 
        else while (n) {
            s = String.fromCharCode(97 + n % 26) + s;
            n = Math.floor(n / 26);
        }
        return s;
    }
    
    // pad("ba", 4) -> "aaba"
    function pad (s, n) {
        while (s.length < n) s = 'a' + s;
        return s;
    }
    

    Usage:

    var from = s2n('azx');
    var to = s2n('baa');
    for (var n = from; n <= to; n++) {
        console.log(pad(n2s(n), 3));
    }
    

    Output:

    azx
    azy
    azz
    baa
    

    Recursivity

    Probably less efficient in terms of memory use or computation time: https://jsperf.com/10-to-26/4.

    function n2s(n) {
        var next = Math.floor(n / 26);
        return (
            next ? n2s(next) : ''
        ) + (
            String.fromCharCode(97 + n % 26)
        );
    }
    
    function s2n(s) {
        return s.length && (
            (s.charCodeAt(0) - 97)
        ) * (
            Math.pow(26, s.length - 1)
        ) + (
            s2n(s.slice(1))
        );
    }
    
    0 讨论(0)
  • 2021-02-08 13:15

    I just want to provide an alternative answer to @procrastinator's (since I can't comment on the answer because I don't have enough points on Stackoverflow). His answer seems like the most generic approach but I can't help and notice that after "z" comes "ba" when op expect it to be "aa". Also, this follows how Excel name it's columns.

    Here is the code with corrections:

    function s2n(s) {
        var pow, n = 0, i = 0;
        while (i++ < s.length) {
            pow = Math.pow(26, s.length - i);
            var charCode = s.charCodeAt(i - 1) - 96;
            n += charCode * pow;
        }
        return n;
    }
    
    function n2s(n) {
        var s = '';  
        var reduce = false;
    
        if (n === undefined) {
            n = 0;
        } else {
            n--;
        }
        while (n !== undefined) {
            s = String.fromCharCode(97 + n % 26) + s;
            n = Math.floor(n / 26);
            if (n === 0) {
                n = undefined;
            } else {
                n--;
            }
        }
        return s;
    }
    

    Instead of starting from 0, this will consider 1 to be "a", 26 to be "z", 27 to be "aa" and so on.

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