it-swarm.com.de

Teilen Sie große Zeichenfolgen in n-große Stücke in JavaScript

Ich möchte eine sehr große Zeichenfolge (sagen wir 10.000 Zeichen) in N-große Stücke teilen.

Was wäre der beste Weg, um dies zu erreichen?

Zum Beispiel: "1234567890" geteilt durch 2 würde ["12", "34", "56", "78", "90"] werden.

Wäre so etwas mit String.prototype.match möglich, und wenn ja, wäre dies der beste Weg, um dies zu tun?

154
tribe84

Sie können so etwas tun:

"1234567890".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "90"]

Die Methode funktioniert weiterhin mit Strings, deren Größe kein genaues Vielfaches der Blockgröße ist:

"123456789".match(/.{1,2}/g);
// Results in:
["12", "34", "56", "78", "9"]

Im Allgemeinen würden Sie für alle Zeichenfolgen, aus denen Sie höchstens Teilstrings in n - extrahieren möchten, Folgendes tun:

str.match(/.{1,n}/g); // Replace n with the size of the substring

Wenn Ihre Zeichenfolge Zeilenumbrüche oder Zeilenumbrüche enthalten kann, würden Sie Folgendes tun:

str.match(/(.|[\r\n]){1,n}/g); // Replace n with the size of the substring

Was die Performance angeht, habe ich dies mit ca. 10.000 Zeichen ausprobiert und es dauerte etwas mehr als eine Sekunde in Chrome. YMMV.

Dies kann auch in einer wiederverwendbaren Funktion verwendet werden:

function chunkString(str, length) {
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
}
341
Vivin Paliath

Endeffekt:

  • match ist sehr ineffizient, slice ist besser, unter Firefox substr/substring ist noch besser
  • match ist für kurze Zeichenfolgen sogar noch ineffizienter (selbst bei zwischengespeichertem Regex - wahrscheinlich aufgrund der Setup-Zeit für Regex-Analysen)
  • match ist bei großen Chunk-Größen sogar noch ineffizienter (wahrscheinlich aufgrund der Unfähigkeit, zu "springen")
  • für längere Zeichenfolgen mit sehr kleiner Chunkgröße übertrifft matchslice auf älteren IE, verliert jedoch auf allen anderen Systemen
  • jsperf rockt
27
Tgr

Ich habe mehrere schnellere Varianten erstellt, die Sie siehe auf jsPerf können. Mein Favorit ist folgender:

function chunkSubstr(str, size) {
  const numChunks = Math.ceil(str.length / size)
  const chunks = new Array(numChunks)

  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
    chunks[i] = str.substr(o, size)
  }

  return chunks
}
23

Dies ist die schnellste und leistungsfähigste Lösung:

function chunkString(str, len) {
  var _size = Math.ceil(str.length/len),
      _ret  = new Array(_size),
      _offset
  ;

  for (var _i=0; _i<_size; _i++) {
    _offset = _i * len;
    _ret[_i] = str.substring(_offset, _offset + len);
  }

  return _ret;
}

Vergleiche es mit den anderen ; Ich gewinne :)

13
user633183

Überraschung! Sie können split zum Teilen verwenden.

var parts = "1234567890 ".split(/(.{2})/).filter(O=>O)

Ergebnisse in [ '12', '34', '56', '78', '90', ' ' ]

7
Fozi
var str = "123456789";
var chunks = [];
var chunkSize = 2;

while (str) {
    if (str.length < chunkSize) {
        chunks.Push(str);
        break;
    }
    else {
        chunks.Push(str.substr(0, chunkSize));
        str = str.substr(chunkSize);
    }
}

alert(chunks); // chunks == 12,34,56,78,9
4
FishBasketGordo

Ich habe eine erweiterte Funktion geschrieben, daher kann die Blocklänge auch ein Array von Zahlen sein, wie [1,3].

String.prototype.chunkString = function(len) {
    var _ret;
    if (this.length < 1) {
        return [];
    }
    if (typeof len === 'number' && len > 0) {
        var _size = Math.ceil(this.length / len), _offset = 0;
        _ret = new Array(_size);
        for (var _i = 0; _i < _size; _i++) {
            _ret[_i] = this.substring(_offset, _offset = _offset + len);
        }
    }
    else if (typeof len === 'object' && len.length) {
        var n = 0, l = this.length, chunk, that = this;
        _ret = [];
        do {
            len.forEach(function(o) {
                chunk = that.substring(n, n + o);
                if (chunk !== '') {
                    _ret.Push(chunk);
                    n += chunk.length;
                }
            });
            if (n === 0) {
                return undefined; // prevent an endless loop when len = [0]
            }
        } while (n < l);
    }
    return _ret;
};

Der Code

"1234567890123".chunkString([1,3])

wird zurückkehren:

[ '1', '234', '5', '678', '9', '012', '3' ]
3
Egon Schmid

it Split's große Zeichenfolge in Kleine Zeichenketten Wörter .

function chunkSubstr(str, words) {
  var parts = str.split(" ") , values = [] , i = 0 , tmpVar = "";
  $.each(parts, function(index, value) {
      if(tmpVar.length < words){
          tmpVar += " " + value;
      }else{
          values[i] = tmpVar.replace(/\s+/g, " ");
          i++;
          tmpVar = value;
      }
  });
  if(values.length < 1 &&  parts.length > 0){
      values[0] = tmpVar;
  }
  return values;
}
2
Haseeb
var l = str.length, lc = 0, chunks = [], c = 0, chunkSize = 2;
for (; lc < l; c++) {
  chunks[c] = str.slice(lc, lc += chunkSize);
}
1
Poetro

Ich würde eine Regex verwenden ...

var chunkStr = function(str, chunkLength) {
    return str.match(new RegExp('[\\s\\S]{1,' + +chunkLength + '}', 'g'));
}
1
alex

Slice () -Methode verwenden:

function returnChunksArray(str, chunkSize) {
  var arr = [];
  while(str !== '') {
    arr.Push(str.slice(0, chunkSize));
    str = str.slice(chunkSize);
  }
  return arr;
}

Dasselbe kann mit der substring () -Methode durchgeführt werden.

function returnChunksArray(str, chunkSize) {
  var arr = [];
  while(str !== '') {
    arr.Push(str.substring(0, chunkSize));
    str = str.substring(chunkSize);
  }
  return arr;
}
0
Placid

In Form einer Prototypfunktion:

String.prototype.lsplit = function(){
    return this.match(new RegExp('.{1,'+ ((arguments.length==1)?(isFinite(String(arguments[0]).trim())?arguments[0]:false):1) +'}', 'g'));
}
0
Awesomolocity

Hier ist der Code, den ich benutze, er verwendet String.prototype.slice .

Ja, die Antwort ist lang, denn sie versucht, den aktuellen Standards so nahe wie möglich zu folgen und enthält natürlich eine angemessene Anzahl von JSDOC comments. Nach der Minifizierung beträgt der Code jedoch nur 828 Bytes und nach der Übertragung nur noch 497 Bytes.

Die 1-Methode, die dies zu String.prototype (unter Verwendung von Object.defineProperty sofern verfügbar) hinzufügt, lautet:

  1. toChunks

Eine Reihe von Tests wurde hinzugefügt, um die Funktionalität zu überprüfen.

Besorgt, dass die Länge des Codes die Leistung beeinflusst? Keine Sorge, http://jsperf.com/chunk-string/3

Ein Großteil des zusätzlichen Codes sorgt dafür, dass der Code in mehreren Javascript-Umgebungen gleich reagiert.

/*jslint maxlen:80, browser:true, devel:true */

/*
 * Properties used by toChunks.
 */

/*property
    MAX_SAFE_INTEGER, abs, ceil, configurable, defineProperty, enumerable,
    floor, length, max, min, pow, prototype, slice, toChunks, value,
    writable
*/

/*
 * Properties used in the testing of toChunks implimentation.
 */

/*property
    appendChild, createTextNode, floor, fromCharCode, getElementById, length,
    log, pow, Push, random, toChunks
*/

(function () {
    'use strict';

    var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1;

    /**
     * Defines a new property directly on an object, or modifies an existing
     * property on an object, and returns the object.
     *
     * @private
     * @function
     * @param {Object} object
     * @param {string} property
     * @param {Object} descriptor
     * @return {Object}
     * @see https://goo.gl/CZnEqg
     */
    function $defineProperty(object, property, descriptor) {
        if (Object.defineProperty) {
            Object.defineProperty(object, property, descriptor);
        } else {
            object[property] = descriptor.value;
        }

        return object;
    }

    /**
     * Returns true if the operands are strictly equal with no type conversion.
     *
     * @private
     * @function
     * @param {*} a
     * @param {*} b
     * @return {boolean}
     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.4
     */
    function $strictEqual(a, b) {
        return a === b;
    }

    /**
     * Returns true if the operand inputArg is undefined.
     *
     * @private
     * @function
     * @param {*} inputArg
     * @return {boolean}
     */
    function $isUndefined(inputArg) {
        return $strictEqual(typeof inputArg, 'undefined');
    }

    /**
     * The abstract operation throws an error if its argument is a value that
     * cannot be converted to an Object, otherwise returns the argument.
     *
     * @private
     * @function
     * @param {*} inputArg The object to be tested.
     * @throws {TypeError} If inputArg is null or undefined.
     * @return {*} The inputArg if coercible.
     * @see https://goo.gl/5GcmVq
     */
    function $requireObjectCoercible(inputArg) {
        var errStr;

        if (inputArg === null || $isUndefined(inputArg)) {
            errStr = 'Cannot convert argument to object: ' + inputArg;
            throw new TypeError(errStr);
        }

        return inputArg;
    }

    /**
     * The abstract operation converts its argument to a value of type string
     *
     * @private
     * @function
     * @param {*} inputArg
     * @return {string}
     * @see https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring
     */
    function $toString(inputArg) {
        var type,
            val;

        if (inputArg === null) {
            val = 'null';
        } else {
            type = typeof inputArg;
            if (type === 'string') {
                val = inputArg;
            } else if (type === 'undefined') {
                val = type;
            } else {
                if (type === 'symbol') {
                    throw new TypeError('Cannot convert symbol to string');
                }

                val = String(inputArg);
            }
        }

        return val;
    }

    /**
     * Returns a string only if the arguments is coercible otherwise throws an
     * error.
     *
     * @private
     * @function
     * @param {*} inputArg
     * @throws {TypeError} If inputArg is null or undefined.
     * @return {string}
     */
    function $onlyCoercibleToString(inputArg) {
        return $toString($requireObjectCoercible(inputArg));
    }

    /**
     * The function evaluates the passed value and converts it to an integer.
     *
     * @private
     * @function
     * @param {*} inputArg The object to be converted to an integer.
     * @return {number} If the target value is NaN, null or undefined, 0 is
     *                   returned. If the target value is false, 0 is returned
     *                   and if true, 1 is returned.
     * @see http://www.ecma-international.org/ecma-262/5.1/#sec-9.4
     */
    function $toInteger(inputArg) {
        var number = +inputArg,
            val = 0;

        if ($strictEqual(number, number)) {
            if (!number || number === Infinity || number === -Infinity) {
                val = number;
            } else {
                val = (number > 0 || -1) * Math.floor(Math.abs(number));
            }
        }

        return val;
    }

    /**
     * The abstract operation ToLength converts its argument to an integer
     * suitable for use as the length of an array-like object.
     *
     * @private
     * @function
     * @param {*} inputArg The object to be converted to a length.
     * @return {number} If len <= +0 then +0 else if len is +INFINITY then
     *                   2^53-1 else min(len, 2^53-1).
     * @see https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
     */
    function $toLength(inputArg) {
        return Math.min(Math.max($toInteger(inputArg), 0), MAX_SAFE_INTEGER);
    }

    if (!String.prototype.toChunks) {
        /**
         * This method chunks a string into an array of strings of a specified
         * chunk size.
         *
         * @function
         * @this {string} The string to be chunked.
         * @param {Number} chunkSize The size of the chunks that the string will
         *                           be chunked into.
         * @returns {Array} Returns an array of the chunked string.
         */
        $defineProperty(String.prototype, 'toChunks', {
            enumerable: false,
            configurable: true,
            writable: true,
            value: function (chunkSize) {
                var str = $onlyCoercibleToString(this),
                    chunkLength = $toInteger(chunkSize),
                    chunked = [],
                    numChunks,
                    length,
                    index,
                    start,
                    end;

                if (chunkLength < 1) {
                    return chunked;
                }

                length = $toLength(str.length);
                numChunks = Math.ceil(length / chunkLength);
                index = 0;
                start = 0;
                end = chunkLength;
                chunked.length = numChunks;
                while (index < numChunks) {
                    chunked[index] = str.slice(start, end);
                    start = end;
                    end += chunkLength;
                    index += 1;
                }

                return chunked;
            }
        });
    }
}());

/*
 * Some tests
 */

(function () {
    'use strict';

    var pre = document.getElementById('out'),
        chunkSizes = [],
        maxChunkSize = 512,
        testString = '',
        maxTestString = 100000,
        chunkSize = 0,
        index = 1;

    while (chunkSize < maxChunkSize) {
        chunkSize = Math.pow(2, index);
        chunkSizes.Push(chunkSize);
        index += 1;
    }

    index = 0;
    while (index < maxTestString) {
        testString += String.fromCharCode(Math.floor(Math.random() * 95) + 32);
        index += 1;
    }

    function log(result) {
        pre.appendChild(document.createTextNode(result + '\n'));
    }

    function test() {
        var strLength = testString.length,
            czLength = chunkSizes.length,
            czIndex = 0,
            czValue,
            result,
            numChunks,
            pass;

        while (czIndex < czLength) {
            czValue = chunkSizes[czIndex];
            numChunks = Math.ceil(strLength / czValue);
            result = testString.toChunks(czValue);
            czIndex += 1;
            log('chunksize: ' + czValue);
            log(' Number of chunks:');
            log('  Calculated: ' + numChunks);
            log('  Actual:' + result.length);
            pass = result.length === numChunks;
            log(' First chunk size: ' + result[0].length);
            pass = pass && result[0].length === czValue;
            log(' Passed: ' + pass);
            log('');
        }
    }

    test();
    log('');
    log('Simple test result');
    log('abcdefghijklmnopqrstuvwxyz'.toChunks(3));
}());
<pre id="out"></pre>

0
Xotic750
const getChunksFromString = (str, chunkSize) => {
    var regexChunk = new RegExp(`.{1,${chunkSize}}`, 'g')   // '.' represents any character
    return str.match(regexChunk)
}

Nennen Sie es nach Bedarf 

console.log(getChunksFromString("Hello world", 3))   // ["Hel", "lo ", "wor", "ld"]
0
Ben Carp

Was ist mit diesem kleinen Code:

function splitME(str, size) {
    let subStr = new RegExp('.{1,' + size + '}', 'g');
    return str.match(subStr);
};
0
Hari
    window.format = function(b, a) {
        if (!b || isNaN(+a)) return a;
        var a = b.charAt(0) == "-" ? -a : +a,
            j = a < 0 ? a = -a : 0,
            e = b.match(/[^\d\-\+#]/g),
            h = e && e[e.length - 1] || ".",
            e = e && e[1] && e[0] || ",",
            b = b.split(h),
            a = a.toFixed(b[1] && b[1].length),
            a = +a + "",
            d = b[1] && b[1].lastIndexOf("0"),
            c = a.split(".");
        if (!c[1] || c[1] && c[1].length <= d) a = (+a).toFixed(d + 1);
        d = b[0].split(e);
        b[0] = d.join("");
        var f = b[0] && b[0].indexOf("0");
        if (f > -1)
            for (; c[0].length < b[0].length - f;) c[0] = "0" + c[0];
        else +c[0] == 0 && (c[0] = "");
        a = a.split(".");
        a[0] = c[0];
        if (c = d[1] && d[d.length -
                1].length) {
            for (var d = a[0], f = "", k = d.length % c, g = 0, i = d.length; g < i; g++) f += d.charAt(g), !((g - k + 1) % c) && g < i - c && (f += e);
            a[0] = f
        }
        a[1] = b[1] && a[1] ? h + a[1] : "";
        return (j ? "-" : "") + a[0] + a[1]
    };

var str="1234567890";
var formatstr=format( "##,###.", str);
alert(formatstr);


This will split the string in reverse order with comma separated after 3 char's. If you want you can change the position.
0
Murali Krish