【问题标题】:Split a string only the at the first n occurrences of a delimiter仅在分隔符的前 n 次出现处拆分字符串
【发布时间】:2011-07-31 17:37:53
【问题描述】:

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

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

【问题讨论】:

标签: javascript


【解决方案1】:

根据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"]

【讨论】:

  • 这将删除第三部分。
  • 嗨,戴文。你的回答帮助了我。你怎么看:var string = 'Split this, but not this', result = string.split(' '), result.push(result.splice(2).join(' '));
  • 虽然简洁,但这并不能处理字符串只有一个空格的情况——结果数组将包含一个额外的空字符串。
  • @riv 好点。对于其他任何人,如果arr.length > 0 ,只需推送最后一部分即可解决此问题。
【解决方案2】:

使用 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"]

【讨论】:

    【解决方案3】:

    splitjoin 与 ES6 特性的组合非常简洁:

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

    【讨论】:

    【解决方案4】:

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

    edit——我突然想到另一种简单的方法是只使用普通的“.split()”,去掉前几个部分,然后只使用“.slice() " 和 ".join()" 其余部分。

    【讨论】:

    • 其实,没有。他会回复["Split", "this,", "but"],而不是他要求的。 split 的限制出人意料地无用,并且与许多其他 split 函数不同。
    • 是的@TJ,这就是为什么我添加了关于重新粘贴“尾巴”的警告。
    • 我刚才评论时不在那里。 :-) 等等,也许是这样。
    • 我的编辑技巧又来了!是的,它的工作方式令人惊讶。
    【解决方案5】:

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

    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"
    

    【讨论】:

    • 在这个例子中它会起作用,但实际上之后可能会出现更多的逗号等。
    • @nines 但这不是你想要做的吗? “仅在前 n 次出现分隔符”
    • 我的例子很愚蠢,对不起。实际上我有一些简单的协议:command + delimiter + options + delimiter + data。前两部分是固定的,所以不会有字符,但数据部分是可变长度的,可以包含任何内容。我只是认为会有一种简短的标准方法来执行此操作,因为 javascript 拆分似乎与其他一些语言不同,它会切断其余部分而不是将其放入其他元素中。
    • @nines 你可以编辑你的问题,并发布一个带有真实字符串和预期输出的示例。
    【解决方案6】:
    var result = [string.split(' ',1).toString(), string.split(' ').slice(1).join(' ')];
    

    结果:

    ["Split", "this, but not this"]
    

    【讨论】:

      【解决方案7】:

      虽然你可以给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;
      }
      

      但即便如此,你最终还是会修改后面部分的空格数。所以我可能只是用老式的 write-your-own-loop 方式来做:

      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

      【讨论】:

        【解决方案8】:

        您好,我有同样的问题,只想拆分几次,找不到任何东西,所以我只是扩展了 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】:

        健全的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"]
        

        专为 Chrome、Firefox、Safari、IE8+ 构建并经过测试。

        【讨论】:

          【解决方案10】:

          又一个有限制的实现;

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

          【讨论】:

            【解决方案11】:

            ES2015

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

            复杂度O(n).

            【讨论】:

            • 使用count - 1 而不是count 来拆分Java
            【解决方案12】:
            var s='Split this, but not this', a=s.split(','), b=a[0].split(' ');
            b.push(a[1]);
            alert(b);
            

            alerts ['Split', 'this', 'but not this']

            【讨论】:

              【解决方案13】:

              我刚刚写的另一个实现:

              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 元素(如果没有足够的分隔符,将使用undefineds 填充);这使得做这种 ES6 的东西是安全的:

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

              【讨论】:

                【解决方案14】:

                我喜欢使用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,' ');
                

                【讨论】:

                  【解决方案15】:

                  没有什么是一个简单的正则表达式做不到的:

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

                  【讨论】:

                    【解决方案16】:

                    在我的例子中,我试图解析 git grep stdout。所以我有一个 {filename}:{linenumber}:{context}。我不喜欢分裂然后加入。我们应该能够一次解析字符串。您可以简单地遍历每个字母并在前两个冒号上拆分。开箱即用的更快方法是使用 match 方法和正则表达式。

                    因此,

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

                    效果很好

                    【讨论】:

                      【解决方案17】:

                      我的通用版本支持 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!");
                      

                      【讨论】:

                        【解决方案18】:

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

                        const splitted = path.split('/')
                        const core = splittedPath.slice(0, 2)
                        const rest = splittedPath.slice(2).join('/')
                        const result = [...core, rest]
                        

                        【讨论】:

                          【解决方案19】:

                          对于仅拆分第一个匹配项的特定情况,下面的代码也很有用。在我的测试中,它的性能比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)];
                          }
                          

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2020-08-11
                            • 2013-06-08
                            • 2019-01-06
                            • 2021-12-08
                            • 1970-01-01
                            • 1970-01-01
                            • 2011-01-28
                            相关资源
                            最近更新 更多