मैं कैसे n वर्णों के खंडों में एक स्ट्रिंग विभाजित कर सकता हूं?


201

जैसा कि शीर्षक कहता है, मुझे एक तार मिला है और मैं n वर्णों के खंडों में विभाजित करना चाहता हूं ।

उदाहरण के लिए:

var str = 'abcdefghijkl';

कुछ जादू के साथ n=3, यह बन जाएगा

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

क्या इसे करने का कोई तरीका है?

जवाबों:


359

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}/इसके बजाय उपयोग करें । (साभार @ मायके)।
  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 वर्णों को हड़प लेगा)।
एरिक

6
के [\s\S]बजाय का उपयोग करें .ताकि newlines पर विफल न हों।
माइक सैमुअल

2
आप हर लाइन पर एक नया चक्र शुरू करना चाह सकते हैं। यदि आपके पास वास्तव में नई लाइनें हैं, तो वे संभवतः किसी प्रकार के संक्रमण का संकेत देते हैं। str.match (/। {1,3} / gm) एक बेहतर विकल्प हो सकता है।
केनेबेक

+1 सावधान: ''.match(/.{1,3}/g) और खाली सरणी के बजाय ''.match(/.{3}/g)वापस लौटें null
वेब_डिजेनर

4
क्या अंक 3 के स्थान पर एक चर होना संभव है?
एना क्लाउडिया

46

यदि आप एक नियमित अभिव्यक्ति का उपयोग नहीं करना चाहते ...

var chunks = [];

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

jsFiddle

... अन्यथा रेगेक्स समाधान बहुत अच्छा है :)


1
यदि आप 3ओपी द्वारा सुझाए गए परिवर्तनशील हैं तो +1 कॉस मैं इसे पसंद करूंगा । यह एक regexp स्ट्रिंग को बदलने की तुलना में अधिक पठनीय है।
डेविड टैंग

यदि आप केवल एक उपयोगी कार्य में उपयोग करने के लिए तैयार लपेट सकते हैं
mmm

1
यह रेगेक्स विकल्प की तुलना में 10 गुना अधिक तेज है, इसलिए मैं इस (एक फ़ंक्शन के अंदर) jsbench.github.io/#9cb819bf1ce429575f8535a2bf72d5a
Job

1
मेरा पिछला कथन क्रोमियम पर लागू होता है (साथ ही, पिछली टिप्पणी को संपादित करने में मुझे बहुत देर हो गई थी इसलिए नया)। फ़ायरफ़ॉक्स पर यह वर्तमान में मेरी मशीन पर "केवल" 30% तेज है, लेकिन यह अभी भी लगातार बेहतर है।
जॉब

क्या यह स्ट्रिंग की विशाल लंबाई पर टिकाऊ है?
जैकब श्नाइडर

22
str.match(/.{3}/g); // => ['abc', 'def', 'ghi', 'jkl']

यह 3मेरे लिए काम करता है लेकिन nullसाथ लौटता है 250। 🤔
जिम

9

इस प्रश्न के पिछले उत्तरों पर निर्माण; निम्न फ़ंक्शन वर्णों की एक स्ट्रिंग ( str) एन-संख्या ( 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;
}
<div id="out"></div>


2

मेरा समाधान (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);

चियर्स


2
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 के बिना साफ समाधान


1
function chunk(er){
return er.match(/.{1,75}/g).join('\n');
}

ऊपर का कार्य है जो मैं बेस 64 चंकिंग के लिए उपयोग करता हूं। यह 75 वर्णों पर एक पंक्ति विराम पैदा करेगा।


भी कर सकता था replace(/.{1,75}/g, '$&\n')
एलेक्स

1

यहां हम प्रत्येक स्ट्रिंग को प्रत्येक 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'));

हमें मिला:

आग | आग | AEG | ईएजी | ई

और यहाँ हम ऐसा ही करते हैं, लेकिन एक सरणी में धक्का देते हैं:

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

हमें मिला:

['फोबा', 'rbazt', 'ruck']

अगर किसी को उपरोक्त कोड को सरल बनाने के तरीके के बारे में पता है, lmk, लेकिन यह तार के लिए ठीक काम करना चाहिए।


आपका पहला स्निपेट अपेक्षित रूप से काम नहीं कर रहा था। मैंने यहां संशोधित किया: jsfiddle.net/omarojo/ksvx2txb/261
omarojo

0

नियमित अभिव्यक्ति का उपयोग किए बिना कुछ साफ समाधान:

/**
* 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/2envahnk/ पर देखे जा सकते हैं । टेस्ट दिखा रहे हैं कि दोनों तरीकों का प्रदर्शन समान है, हो सकता है कि फर्स्ट लुक पर regexp सॉल्यूशन थोड़ा तेज हो, लेकिन इसे खुद जज करें।


0

के साथ .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' ]     // I don't know why is not [ 'abc', 'def', 'ghi', 'jkl' , '' ], comment?
var replaced = str.replace( /(?<=^(.{3})+)/g, ' || ')  // 'abc || def || ghi || jkl || '

समूह को अनदेखा करना /(?:... इसमें )/कोई आवश्यकता नहीं है, .replaceलेकिन .splitसमूहों को गिरफ्तार करने के लिए जोड़ रहा है:

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

0

यह नियमित अभिव्यक्ति या स्पष्ट छोरों के बिना करने का एक तरीका है, हालांकि यह एक लाइनर की परिभाषा को थोड़ा बढ़ा रहा है:

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पर एक एकल मान लौटाता है, लेकिन इस मामले में एकल मान एक सरणी होता है, और जैसा कि हम प्रत्येक वर्ण के ऊपर से गुजरते हैं, हम उस सरणी में अंतिम आइटम पर जोड़ देते हैं। एक बार सरणी में अंतिम आइटम लक्ष्य की लंबाई तक पहुँच जाता है, हम एक नया सरणी आइटम जोड़ते हैं।


0

थोड़ी देर बाद चर्चा में आ रहे हैं लेकिन यहाँ एक भिन्नता है जो कि सब्स्क्राइबिंग + सरणी पुश एक की तुलना में थोड़ी तेज़ है।

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

लूप के भाग के रूप में अंतिम मान की पूर्व-गणना करना विकल्प के अंदर इनलाइन गणित करने से अधिक तेज़ है। मैंने इसे फ़ायरफ़ॉक्स और क्रोम दोनों में परीक्षण किया है और वे दोनों स्पीडअप दिखाते हैं।

आप इसे यहाँ आज़मा सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.