【问题标题】:How can I split a string into segments of n characters?如何将字符串拆分为 n 个字符的段?
【发布时间】:2011-09-09 17:05:34
【问题描述】:

正如标题所说,我有一个字符串,我想分成 n 个字符的段。

例如:

var str = 'abcdefghijkl';

经过n=3的一些魔术,它会变成

var arr = ['abc','def','ghi','jkl'];

有没有办法做到这一点?

【问题讨论】:

标签: javascript arrays string split


【解决方案1】:

如果您不想使用正则表达式...

var chunks = [];

for (var i = 0, charsLength = str.length; i < charsLength; i += 3) {
    chunks.push(str.substring(i, i + 3));
}

jsFiddle.

...否则正则表达式解决方案非常好:)

【讨论】:

  • +1 因为如果 3 是 OP 建议的变量,我更喜欢这个。它比连接正则表达式字符串更具可读性。
  • 如果你能把它包装成一个可以使用的有用函数
  • 这比正则表达式选项快 10 倍以上,所以我会选择这个(在函数内部)jsbench.github.io/#9cb819bf1ce429575f8535a211f72d5a
  • 我之前的声明适用于 Chromium(另外,我编辑之前的评论太晚了,因此是新的评论)。在 Firefox 上,它目前在我的机器上“仅”快了 30%,但这仍然更好。
  • 这对于长长的字符串是否可持续?
【解决方案2】:
str.match(/.{3}/g); // => ['abc', 'def', 'ghi', 'jkl']

【讨论】:

  • 这适用于我的3,但返回null250。 ?
【解决方案3】:

var str = 'abcdefghijkl';
console.log(str.match(/.{1,3}/g));

注意:使用{1,3} 而不是只使用{3} 来包含不是3 倍数的字符串长度的余数,例如:

console.log("abcd".match(/.{1,3}/g)); // ["abc", "d"]

更多细节:

  1. 如果您的字符串可能包含换行符(您希望将其计为一个字符而不是拆分字符串),那么. 将不会捕获这些。请改用/[\s\S]{1,3}/。 (感谢@Mike)。
  2. 如果您的字符串为空,那么match() 将返回null,而您可能期望一个空数组。通过附加 || [] 来防止这种情况发生。

所以你可能会得到:

var str = 'abcdef \t\r\nghijkl';
var parts = str.match(/[\s\S]{1,3}/g) || [];
console.log(parts);

console.log(''.match(/[\s\S]{1,3}/g) || []);

【讨论】:

  • 这在技术上是更好的答案,因为它会从不能被 3 整除的字符串中抓取所有文本(它会抓取最后 2 或 1 个字符)。
  • 使用[\s\S] 而不是.,以免换行失败。
  • 您可能希望在每一行上开始一个新循环。如果您确实有换行符,它们可能表示某种类型的转换。 str.match(/.{1,3}/gm) 可能是更好的选择。
  • +1 小心: ''.match(/.{1,3}/g)''.match(/.{3}/g) 返回 null 而不是空数组。
  • 数字3可以用变量代替吗?
【解决方案4】:

在此问题的先前答案的基础上;以下函数将拆分字符串 (str) n 个 (size) 字符。

function chunk(str, size) {
    return str.match(new RegExp('.{1,' + size + '}', 'g'));
}

演示

(function() {
  function chunk(str, size) {
    return str.match(new RegExp('.{1,' + size + '}', 'g'));
  }
  
  var str = 'HELLO WORLD';
  println('Simple binary representation:');
  println(chunk(textToBin(str), 8).join('\n'));
  println('\nNow for something crazy:');
  println(chunk(textToHex(str, 4), 8).map(function(h) { return '0x' + h }).join('  '));
  
  // Utiliy functions, you can ignore these.
  function textToBin(text) { return textToBase(text, 2, 8); }
  function textToHex(t, w) { return pad(textToBase(t,16,2), roundUp(t.length, w)*2, '00'); }
  function pad(val, len, chr) { return (repeat(chr, len) + val).slice(-len); }
  function print(text) { document.getElementById('out').innerHTML += (text || ''); }
  function println(text) { print((text || '') + '\n'); }
  function repeat(chr, n) { return new Array(n + 1).join(chr); }
  function textToBase(text, radix, n) {
    return text.split('').reduce(function(result, chr) {
      return result + pad(chr.charCodeAt(0).toString(radix), n, '0');
    }, '');
  }
  function roundUp(numToRound, multiple) { 
    if (multiple === 0) return numToRound;
    var remainder = numToRound % multiple;
    return remainder === 0 ? numToRound : numToRound + multiple - remainder;
  }
}());
#out {
  white-space: pre;
  font-size: 0.8em;
}
&lt;div id="out"&gt;&lt;/div&gt;

【讨论】:

    【解决方案5】:
    function chunk(er){
    return er.match(/.{1,75}/g).join('\n');
    }
    

    上面的函数是我用于 Base64 分块的。它将创建一个每 75 个字符的换行符。

    【讨论】:

    • 也可以replace(/.{1,75}/g, '$&amp;\n').
    【解决方案6】:

    一些不使用正则表达式的干净解决方案:

    /**
    * Create array with maximum chunk length = maxPartSize
    * It work safe also for shorter strings than part size
    **/
    function convertStringToArray(str, maxPartSize){
    
      const chunkArr = [];
      let leftStr = str;
      do {
    
        chunkArr.push(leftStr.substring(0, maxPartSize));
        leftStr = leftStr.substring(maxPartSize, leftStr.length);
    
      } while (leftStr.length > 0);
    
      return chunkArr;
    };
    

    使用示例 - https://jsfiddle.net/maciejsikora/b6xppj4q/.

    我还尝试将我的解决方案与被选为正确答案的正则表达式进行比较。一些测试可以在 jsfiddle -https://jsfiddle.net/maciejsikora/2envahrk/ 上找到。测试表明两种方法具有相似的性能,可能乍一看正则表达式解决方案要快一点,但请自行判断。

    【讨论】:

      【解决方案7】:

      我的解决方案(ES6 语法):

      const source = "8d7f66a9273fc766cd66d1d";
      const target = [];
      for (
          const array = Array.from(source);
          array.length;
          target.push(array.splice(0,2).join(''), 2));
      

      我们甚至可以用这个创建一个函数:

      function splitStringBySegmentLength(source, segmentLength) {
          if (!segmentLength || segmentLength < 1) throw Error('Segment length must be defined and greater than/equal to 1');
          const target = [];
          for (
              const array = Array.from(source);
              array.length;
              target.push(array.splice(0,segmentLength).join('')));
          return target;
      }
      

      那么你就可以很容易地以可重用的方式调用函数了:

      const source = "8d7f66a9273fc766cd66d1d";
      const target = splitStringBySegmentLength(source, 2);
      

      干杯

      【讨论】:

        【解决方案8】:

        这里我们每隔 n 个字符将一个字符串与另一个字符串穿插:

        export const intersperseString = (n: number, intersperseWith: string, str: string): string => {
        
          let ret = str.slice(0,n), remaining = str;
        
          while (remaining) {
            let v = remaining.slice(0, n);
            remaining = remaining.slice(v.length);
            ret += intersperseWith + v;
          }
        
          return ret;
        
        };
        

        如果我们像这样使用上面的:

        console.log(splitString(3,'|', 'aagaegeage'));
        

        我们得到:

        aag|aag|aeg|eag|e

        在这里我们做同样的事情,但推送到一个数组:

        export const sperseString = (n: number, str: string): Array<string> => {
        
          let ret = [], remaining = str;
        
          while (remaining) {
            let v = remaining.slice(0, n);
            remaining = remaining.slice(v.length);
            ret.push(v);
          }
        
          return ret;
        
        };
        

        然后运行它:

        console.log(sperseString(5, 'foobarbaztruck'));
        

        我们得到:

        ['fooba','rbazt','ruck']

        如果有人知道简化上述代码的方法,lmk,但它应该适用于字符串。

        【讨论】:

        【解决方案9】:

        如果您确实需要坚持使用.split 和/或.raplace,请使用/(?&lt;=^(?:.{3})+)(?!$)/g

        对于.split

        var arr = str.split( /(?<=^(?:.{3})+)(?!$)/ )
        // [ 'abc', 'def', 'ghi', 'jkl' ]
        

        对于.replace

        var replaced = str.replace( /(?<=^(?:.{3})+)(?!$)/g, ' || ' )
        // 'abc || def || ghi || jkl'
        



        /(?!$)/ 不会停在字符串的末尾。没有它:

        var arr = str.split( /(?<=^(?:.{3})+)/ )
        // [ 'abc', 'def', 'ghi', 'jkl' ] // is fine
        var replaced = str.replace( /(?<=^(.{3})+)/g, ' || ')
        // 'abc || def || ghi || jkl || ' // not fine
        

        忽略组/(?:...)/ 是为了防止数组中的条目重复。没有它:

        var arr = str.split( /(?<=^(.{3})+)(?!$)/ )
        // [ 'abc', 'abc', 'def', 'abc', 'ghi', 'abc', 'jkl' ] // not fine
        var replaced = str.replace( /(?<=^(.{3})+)(?!$)/g, ' || ' )
        // 'abc || def || ghi || jkl' // is fine
        

        【讨论】:

          【解决方案10】:
          const chunkStr = (str, n, acc) => {     
              if (str.length === 0) {
                  return acc
              } else {
                  acc.push(str.substring(0, n));
                  return chunkStr(str.substring(n), n, acc);
              }
          }
          const str = 'abcdefghijkl';
          const splittedString = chunkStr(str, 3, []);
          

          没有 REGEX 的清洁解决方案

          【讨论】:

            【解决方案11】:

            这是一种无需正则表达式或显式循环的方法,尽管它稍微扩展了单行的定义:

            const input = 'abcdefghijlkm';
            
            // Change `3` to the desired split length.
            const output = input.split('').reduce((s, c) => {let l = s.length-1; (s[l] && s[l].length < 3) ? s[l] += c : s.push(c); return s;}, []);
            
            console.log(output);  // output: [ 'abc', 'def', 'ghi', 'jlk', 'm' ]
            

            它的工作原理是将字符串拆分为单个字符的数组,然后使用Array.reduce 遍历每个字符。通常reduce 会返回单个值,但在这种情况下,单个值恰好是一个数组,并且当我们传递每个字符时,我们将其附加到该数组中的最后一项。一旦数组中的最后一项达到目标长度,我们就追加一个新的数组项。

            【讨论】:

              【解决方案12】:

              稍后讨论,但这里的变体比子字符串 + 数组推送快一点。

              // substring + array push + end precalc
              var chunks = [];
              
              for (var i = 0, e = 3, charsLength = str.length; i < charsLength; i += 3, e += 3) {
                  chunks.push(str.substring(i, e));
              }
              

              在 for 循环中预先计算结束值比在子字符串中进行内联数学运算要快。我已经在 Firefox 和 Chrome 中对其进行了测试,它们都显示了加速。

              你可以试试here

              【讨论】:

                【解决方案13】:
                    var b1 = ""; 
                    function myFunction(n) { 
                    if(str.length>=3){
                     var a = str.substring(0,n);
                     b1 += a+ "\n"
                     str = str.substring(n,str.length)
                     myFunction(n) 
                    } 
                    else{ 
                    if(str.length>0){
                    b1 += str 
                    } 
                    console.log(b1)
                     } 
                    }
                  myFunction(4)
                

                【讨论】:

                  【解决方案14】:

                  试试这个简单的代码,它会像魔术一样工作!

                  let letters = "abcabcabcabcabc";
                  // we defined our variable or the name whatever
                  let a = -3;
                  let finalArray = [];
                  for (let i = 0; i <= letters.length; i += 3) {
                      finalArray.push(letters.slice(a, i));
                    a += 3;
                  }
                  // we did the shift method cause the first element in the array will be just a string "" so we removed it
                  finalArray.shift();
                  // here the final result
                  console.log(finalArray);
                  

                  【讨论】:

                  • 它有效,我 +1
                  【解决方案15】:

                  如果您需要将一个非常大的 html 字符串拆分为较小的 html 字符串并将它们添加到 .txt 文件中的新行中,您可以在此处阅读我的答案。

                  https://stackoverflow.com/a/70287092/13795525

                  【讨论】:

                    【解决方案16】:

                    我最喜欢的答案是 gouder hicham 的。但我对其进行了一些修改,以便对我更有意义。

                    let myString = "Able was I ere I saw elba";
                    
                    let splitString = [];
                    for (let i = 0; i < myString.length; i = i + 3) {
                        splitString.push(myString.slice(i, i + 3));
                    }
                    
                    console.log(splitString);
                    

                    这是代码的功能化版本。

                    
                    function stringSplitter(myString, chunkSize) {
                        let splitString = [];
                        for (let i = 0; i < myString.length; i = i + chunkSize) {
                            splitString.push(myString.slice(i, i + chunkSize));
                        }
                        return splitString;
                    }
                    

                    以及函数的用途:

                    let myString = "Able was I ere I saw elba";
                    let mySplitString = stringSplitter(myString, 3);
                    console.log(mySplitString);
                    

                    结果如下:

                    >(9) ['Abl', 'e w', 'as ', 'I e', 're ', 'I s', 'aw ', 'elb', 'a']
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-03-17
                      相关资源
                      最近更新 更多