仅在分隔符的前n次出现时拆分字符串

时间:2011-04-07 13:54:08

标签: javascript

我想仅在分隔符的前n次出现时拆分字符串。我知道,我可以使用循环将它们添加到一起,但是不是更直接的方法吗?

var string = 'Split this, but not this';    
var result = new Array('Split', 'this,', 'but not this');

19 个答案:

答案 0 :(得分:33)

根据MDN

string.split(separator, limit);

<强>更新

var string = 'Split this, but not this',
    arr = string.split(' '),
    result = arr.slice(0,2);

result.push(arr.slice(2).join(' ')); // ["Split", "this,", "but not this"]

更新版本2(一个slice更短):

var string = 'Split this, but not this',
    arr = string.split(' '),
    result = arr.splice(0,2);

result.push(arr.join(' ')); // result is ["Split", "this,", "but not this"]

答案 1 :(得分:16)

使用Array.slice:

function splitWithTail(str,delim,count){
  var parts = str.split(delim);
  var tail = parts.slice(count).join(delim);
  var result = parts.slice(0,count);
  result.push(tail);
  return result;
}

结果:

splitWithTail(string," ",2)
// => ["Split", "this,", "but not this"]

答案 2 :(得分:6)

JavaScript“.split()”函数已接受第二个参数,给出要执行的最大拆分数。但是,它不会保留原始字符串的尾端;你必须重新粘上它。

另一种方法是用正则表达式迭代地剪掉字符串的前导部分,当你达到限制时停止。

var str = "hello out there cruel world";
var parts = [];
while (parts.length < 3) { // "3" is just an example
  str = str.replace(/^(\w+)\s*(.*)$/, function(_, word, remainder) {
    parts.push(word);
    return remainder;
  });
}
parts.push(str);

编辑 - 它只是发生在我身上,另一个简单的方法是使用普通的“.split()”,取出前几个部分,然后只是“.slice() “和”.join()“其余的。

答案 3 :(得分:5)

splitjoin与ES6功能的结合确实非常简洁:

let [str1, str2, ...str3] = string.split(' ');
str3 = str3.join(' ');

答案 4 :(得分:3)

为此,您可以使用Split(分隔符)并选择分隔符。

var testSplit = "Split this, but not this";
var testParts= testSplit.Split(",");

var firstPart = testParts[1];

// firstPart = "Split this"

我的语法不是100%我在很长一段时间内没有使用过javascript。但我知道这就是它的完成方式......

编辑**对不起,我的错误。现在我相信我知道你的要求,我认为最简单的方法是使用substr。非常简单,无需循环。刚刚做了一个例子,效果很好

// so first, we want to get everything from 0 - the first occurence of the comma.
// next, we want to get everything after the first occurence of the comma.  (if you only define one parameter, substr will take everything after that parameter.

var testString = "Split this, but this part, and this part are one string";
var part1 = testString.substr(0,testString.indexOf(',')); 
var part2 = testString.substr(testString.indexOf(','));

//part1 = "Split this"
//part2= "but this part, and this part are one string"

答案 5 :(得分:2)

虽然你可以给split一个限制,但你不会得到你所说的你想要的东西。不幸的是,你必须自己动手,例如:

var string = 'Split this, but not this';
var result = string.split(' ');

if (result.length > 3) {
    result[2] = result.slice(2).join(' ');
    result.length = 3;
}

但即便如此,你最终还是会修改后面部分的空格数量。所以我可能只是采用老式的自编循环方式:

function splitWithLimit(str, delim, limit) {
  var index,
      lastIndex = 0,
      rv = [];

  while (--limit && (index = str.indexOf(delim, lastIndex)) >= 0) {
    rv.push(str.substring(lastIndex, index));
    lastIndex = index + delim.length;
  }
  if (lastIndex < str.length) {
    rv.push(str.substring(lastIndex));
  }
  return rv;
}

Live copy

答案 6 :(得分:2)

#!/usr/bin/perl

use strict;
use warnings;
use threads;
use threads::shared;

my $run : shared;
$run = 1;

sub sub1 {
   my $count = 0;
   while ($run) {
      $count++;
      print("\$count is $count\n");
      sleep(1);
   }
   print "Terminating\n";
}


my $thr = threads->create( \&sub1 );    # Spawn the thread

sleep(15);                               # Let thread run for awhile
$run = 0;
$thr->join;

结果:

var result = [string.split(' ',1).toString(), string.split(' ').slice(1).join(' ')];

答案 7 :(得分:1)

使用适当的RegEx支持改进版本的limit实施版:

function splitWithTail(value, separator, limit) {
    var pattern, startIndex, m, parts = [];

    if(!limit) {
        return value.split(separator);
    }

    if(separator instanceof RegExp) {
        pattern = new RegExp(separator.source, 'g' + (separator.ignoreCase ? 'i' : '') + (separator.multiline ? 'm' : ''));
    } else {
        pattern = new RegExp(separator.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1'), 'g');
    }

    do {
        startIndex = pattern.lastIndex;
        if(m = pattern.exec(value)) {
            parts.push(value.substr(startIndex, m.index - startIndex));
        }
    } while(m && parts.length < limit - 1);
    parts.push(value.substr(pattern.lastIndex));

    return parts;
}

用法示例:

splitWithTail("foo, bar, baz", /,\s+/, 2); // -> ["foo", "bar, baz"]

专为&amp;在Chrome,Firefox,Safari,IE8 +中测试。

答案 8 :(得分:1)

您好我有同样的问题只想分开几次,无法找到任何东西所以我只是扩展了DOM - 只是一个快速而肮脏的解决方案,但它的工作原理:)

String.prototype.split = function(seperator,limit) {
    var value = "";
    var hops  = [];

    // Validate limit
    limit = typeof(limit)==='number'?limit:0;

    // Join back given value
    for ( var i = 0; i < this.length; i++ ) { value += this[i]; }

    // Walkthrough given hops
    for ( var i = 0; i < limit; i++ ) {
        var pos = value.indexOf(seperator);
        if ( pos != -1 ) {
            hops.push(value.slice(0,pos));
            value = value.slice(pos + seperator.length,value.length)

        // Done here break dat
        } else {
            break;
        }
    }
    // Add non processed rest and return
    hops.push(value)
    return hops;
}

在你的情况下看起来像那样

>>> "Split this, but not this".split(' ',2)
["Split", "this,", "but not this"]

答案 9 :(得分:0)

我刚写的另一个实现:

export function split(subject, separator, limit=undefined, pad=undefined) {
    if(!limit) {
        return subject.split(separator);
    }
    if(limit < 0) {
        throw new Error(`limit must be non-negative`);
    }
    let result = [];
    let fromIndex = 0;
    for(let i=1; i<limit; ++i) {
        let sepIdx = subject.indexOf(separator, fromIndex);
        if(sepIdx < 0) {
            break;
        }
        let substr = subject.slice(fromIndex, sepIdx);
        result.push(substr);
        fromIndex = sepIdx + separator.length;
    }
    result.push(subject.slice(fromIndex));
    while(result.length < limit) {
        result.push(pad);
    }
    return result;
}

不使用正则表达式,也不会过度拆分和重新加入。

此版本可以准确保证limit元素(如果没有足够的分隔符,则会填充undefined s);这样可以安全地完成这种ES6的工作:

let [a,b,c] = split('a$b','$',3,null);
// a = 'a', b = 'b', c = null

答案 10 :(得分:0)

我喜欢使用shift

function splitFirstN(str,n,delim){
    var parts = str.split(delim);
    var r = [];
    for(var i = 0; i < n; i++){
        r.push(parts.shift());
    }
    r.push(parts.join(delim));
    return r;
}

var str = 'Split this, but not this';    
var result = splitFirstN(str,2,' ');

答案 11 :(得分:0)

var s='Split this, but not this', a=s.split(','), b=a[0].split(' ');
b.push(a[1]);
alert(b);

提醒['拆分','此','但不是这个']

答案 12 :(得分:0)

一个简单的正则表达式无法做到:

&#13;
&#13;
const string = 'Split this, but not this';
console.log(string.match(/^(\S+)\s*(\S+)?\s*([\s\S]+)?$/).slice(1));
&#13;
&#13;
&#13;

答案 13 :(得分:0)

在我的情况下,我试图解析git grep stdout。所以我有一个{filename}:{linenumber}:{context}。我不喜欢分裂然后加入。我们应该能够解析一次字符串。您可以简单地单步执行每个字母并分割前两个冒号。开箱即用的更快捷的方法是使用匹配方法和正则表达式。

因此,

txt.match(/(.+):(\d+):(.*)/)

效果很好

答案 14 :(得分:0)

另一个有限制的实施;

// takes string input only
function split(input, separator, limit) {
    input = input.split(separator);
    if (limit) {
        input = input.slice(0, limit - 1).concat(input.slice(limit - 1).join(separator));
    }
    return input;
}

答案 15 :(得分:0)

我的版本,通用,支持RegExp和非RegExp分隔符。高度优化。提供测试。 原因:由于其他RegExp版本充满了错误,这不是一个简单的功能。

<强>用法

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

<强>代码

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;
}

<强>测试

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!");

答案 16 :(得分:0)

ES2015

const splitAndAppend = (str, delim, count) => {
    const arr = str.split(delim);
    return [...arr.splice(0, count), arr.join(delim)];
}

复杂性 O(n)

答案 17 :(得分:0)

就我而言,这解决了我的问题:

echo url('/');
// http://localhost/laravel/public

答案 18 :(得分:0)

对于只拆分第一次出现的特定情况,下面的代码也很有用。在我的测试中,它的表现比 most voted answer 好得多(Chrome 中约为 40%,Firefox 中约为 200%)。

https://jsbench.me/nckrqnwcry/1

function split(term = '', sep = ',') {
    const split = term.split(sep, 1);
    return [split[0], term.substr(split[0].length + sep.length)];
}