Split a string only the at the first n occurrences of a delimiter

后端 未结 18 932
有刺的猬
有刺的猬 2020-12-24 06:22

I\'d like to split a string only the at the first n occurrences of a delimiter. I know, I could add them together using a loop, but isn\'t there a more straight forward appr

18条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-24 06:49

    My version, universal, supports RegExp and non-RegExp delimiters. Highly optimized. Tests provided. Why: since other RegExp versions are full of bugs and this is not a trivial function.

    Usage:

    "a b  c   d".split_with_tail(/ +/,3) = ['a','b','c   d']
    "a b  c   d".split_with_tail(' ',3) = ['a','b',' c   d']
    

    Code

    String.prototype.split_with_tail = function(delimiter,limit)
    {
        if( typeof(limit) !== 'number' || limit < 1 ) return this.split(delimiter,limit);
    
        var parts = this.split(delimiter,limit+1);
        if( parts.length <= limit ) return parts;
        parts.splice(-2,2);
    
        limit = Math.floor(limit) - 1; // used later as index, speed optimization; limit can be float ..
        if( delimiter instanceof RegExp ) {
            // adds 'g' flag to any regexp:
            delimiter += '';
            var len = delimiter.lastIndexOf('/');
            delimiter = new RegExp(delimiter.slice(1, len), delimiter.slice(len + 1)+'g');
    
            len = 0;
            while(limit--) len += parts[limit].length + (delimiter.exec(this))[0].length;
        }
        else {
            var len = limit * (''+delimiter).length;
            while(limit--) len += parts[limit].length;
        }
    
        parts.push(this.substring(len)); // adds tail, finally
        return parts;
    }
    

    Tests

    function test(str,delimiter,limit,result) {
        if( JSON.stringify(result) !== JSON.stringify(str.split_with_tail(delimiter,limit)) ) {
            console.log(arguments);
            console.log(str.split_with_tail(delimiter,limit));
            throw "lol";
        }
    }
    test('',/ +/,undefined,['']);
    test('',/ +/,3,['']);
    test('a',/ +/,0.1,[]);
    test('a',/ +/,1,['a']);
    test('a a',/ +/,1,['a a']);
    test('a a',/ +/,2.1,['a','a']);
    test('a a a',/ +/,2.9,['a','a a']);
    test('aaaaa aa a',/ +/,1,['aaaaa aa a']);
    test('aaaaa aa a',/ +/,2,['aaaaa', 'aa a']);
    test('a a',/ +/,2,['a','a']);
    test('a',/ +/,3,['a']);
    test('a a',/ +/,3,['a','a']);
    test('a a  a',/ +/,3,['a','a','a']);
    test('a a  a  a',/ +/,3,['a','a','a  a']);
    test('a a  a  a',/ +/,4,['a','a','a','a']);
    test('a aa  aaa  ',/ +/,4,['a','aa','aaa','']);
    test('a a  a  a',/ +/,2,['a','a  a  a']);
    test('a a  a  a',/ +/,1,['a a  a  a']);
    test('a a  a  a',/ +/,0,[]);
    test('a a  a  a',/ +/,undefined,['a','a','a','a']);
    test('a a  a  a',/ +/,-1,['a','a','a','a']);
    
    test('a',' ',3,['a']);
    test('aaaaa aa a',' ',2,['aaaaa', 'aa a']);
    test('aaaaa  aa  a','  ',2,['aaaaa','aa  a']);
    test('a a a',' ',3,['a','a','a']);
    test('a a a a',' ',3,['a','a','a a']);
    test('a a  a a',' ',3,['a','a',' a a']);
    test('a a  a a',' ',2,['a','a  a a']);
    test('a a  a a',' ',1,['a a  a a']);
    test('a a  a a',' ',0,[]);
    test('a a  a a',' ',undefined,['a','a','','a','a']);
    test('a a  a a',' ',-1,['a','a','','a','a']);
    test('1232425',2,3,['1','3','425']);
    console.log("good!");
    

提交回复
热议问题