विभाजित स्ट्रिंग केवल निर्दिष्ट चरित्र के पहले उदाहरण पर


271

मेरे कोड में मैंने एक स्ट्रिंग पर आधारित विभाजन किया _और सरणी में दूसरा आइटम ले लिया।

var element = $(this).attr('class');
var field = element.split('_')[1];

लेता है good_luckऔर मुझे प्रदान करता है luck। बहुत अच्छा काम करता है!

लेकिन, अब मेरे पास एक वर्ग है जो दिखता है good_luck_buddy। दूसरे को अनदेखा करने _और मुझे देने के लिए मुझे अपनी जावास्क्रिप्ट कैसे मिलेगी luck_buddy?

मैं इसे var field = element.split(new char [] {'_'}, 2);एसी # stackoverflow जवाब में मिला, लेकिन यह काम नहीं करता है। मैंने इसे jsFiddle पर आजमाया ...

जवाबों:


406

कोष्ठक कैप्चरिंग का उपयोग करें :

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"

वे के रूप में परिभाषित कर रहे हैं

यदि separatorकोष्ठक कैप्चर करना शामिल है, तो मिलान किए गए परिणाम सरणी में वापस आ जाते हैं।

तो इस मामले में हम विभाजित करना चाहते हैं _.+(यानी विभाजन विभाजक एक उप स्ट्रिंग के साथ शुरू होता है _) लेकिन परिणाम को हमारे विभाजक का कुछ हिस्सा (यानी सब कुछ बाद में _) होने दें।

इस उदाहरण में हमारा विभाजक (मिलान _(.+)) है _luck_buddyऔर कैप्चर किया गया समूह (विभाजक के भीतर) है lucky_buddy। कोष्ठक के कैप्चरिंग के बिना luck_buddy(मिलान .+) परिणाम सरणी में शामिल नहीं किया गया होगा क्योंकि यह साधारण के साथ मामला है splitकि विभाजक परिणाम में शामिल नहीं हैं।


21
आपको भी () की आवश्यकता नहीं है, बस पहले _ के बाद 1 और अधिक वर्ण कैप्चर करने के लिए /_(.+)/ का उपयोग करें
मार्क

3
बहुत खूबसूरत। एक जादू की तरह काम करता है। धन्यवाद।
प्रात:

12
बस स्पष्ट होने के लिए, यह समाधान काम करता है, क्योंकि पहले के बाद सब कुछ _एक कैप्चरिंग समूह के अंदर मेल खाता है, और उस कारण के लिए टोकन सूची में जोड़ा जाता है।
एलन मूर

28
किसी को पता है कि मुझे इसके साथ एक अतिरिक्त खाली स्ट्रिंग तत्व क्यों मिलता है: में: "Aspect Ratio: 16:9".split(/:(.+)/)बाहर:["Aspect Ratio", " 16:9", ""]
katy lavallee

4
@katylavallee - इससे मदद मिल सकती है: stackoverflow.com/questions/12836062/… चूंकि विभाजक है ": 16:9", विभाजक के बाद कुछ भी नहीं है, इस प्रकार अंत में खाली स्ट्रिंग का निर्माण होता है।
डेरेक 會 功夫 ere

231

आपको नियमित अभिव्यक्तियों और सरणियों की क्या आवश्यकता है?

myString = myString.substring(myString.indexOf('_')+1)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)


5
स्ट्रिंग! == स्ट्रिंग। जावास्क्रिप्ट केस संवेदी है।
kennebec

3
मुझे लगता है कि यह सबसे अच्छा जवाब है। यह _लिखकर दूसरे के बाद स्ट्रिंग प्राप्त करना भी संभव है :myString.substring( myString.indexOf('_', myString().indexOf('_') + 1) + 1 )
muratgozel

9
उत्तर स्ट्रिंग के दूसरे भाग को आउटपुट करता है। क्या होगा यदि आप पहला भाग भी चाहते हैं? आपके साथ var str = "good_luck_buddy", res = str.split(/_(.+)/);सभी भाग मिलते हैं:console.log(res[0]); console.log(res[1]);
सूर्य

1
@PeterLeger को विभाजित होने दें = [ string.substring(0, string.indexOf(options.divider)), string.substring(string.indexOf(options.divider) + 1) ]वहां आपके पास है। इसके अलावा चर सुई के समर्थन के साथ
स्टीफन

यह जीनियस है!
स्टिकओवरफ़्लो

36

मैं हर कीमत पर RegExp से बचता हूं। यहाँ एक और बात है जो आप कर सकते हैं:

"good_luck_buddy".split('_').slice(1).join('_')

18
RegExp से डरने वाले को कभी नहीं बताया जा सकता है कि RegExp कितना शानदार है। आपको खुद दरवाजा खोजने की जरूरत है। एक बार जब आप वहाँ होंगे, तो आप कभी पीछे मुड़कर नहीं देखेंगे। मुझसे कुछ वर्षों में फिर से पूछें और आप बताएंगे कि यह कितना शानदार है।
क्रिस्टियान वेस्टरबेक

3
@ योनस लाल गोली ले लो!
19

2
@ योनस हाँ, लाल गोली ले लो! यह आपके जीवन को तेज कर देगा, यहां तक ​​कि छोटे तारों के लिए भी: jsperf.com/split-by-first-colon
जूलियन एफ। वेनर्ट

15
हा! मैंने यह टिप्पणी 4+ साल पहले लिखी थी। मैं निश्चित रूप से अब RegExp के साथ बोर्ड पर हूँ! :)
योनस

2
@ आप बेहतर नहीं हैं। जरूरत पड़ने पर RegExp कमाल का है । यहां मामला नहीं है। अद्यतन परीक्षण की जाँच करें: jsperf.com/split-by-first-colon/2
धात्विक

11

पहले उदाहरण को एक अद्वितीय प्लेसहोल्डर से बदलें फिर वहां से विभाजित करें।

"good_luck_buddy".replace(/\_/,'&').split('&')

["good","luck_buddy"]

यह अधिक उपयोगी है जब विभाजन के दोनों किनारों की आवश्यकता होती है।


2
यह स्ट्रिंग पर एक अनावश्यक बाधा डालता है।
यान फोटो

यह उत्तर मेरे लिए काम आया जब उपरोक्त सभी उत्तर नहीं थे।
GuitarViking

1
@YanFoto आप 'और' का उपयोग करके मतलब है? यह कुछ भी हो सकता है।
sebjwallace

2
@sebjwallace आप जो भी चुनते हैं, इसका मतलब है कि आप उस चरित्र को स्ट्रिंग में नहीं रख सकते। उदाहरण के लिए "फिश एंड चिप्स_रे_ग्रीट" देता है [मछली, चिप्स, are_great] मुझे लगता है।
जो

@ जो आप 'और' के बजाय कुछ भी उपयोग कर सकते हैं - यह सिर्फ एक उदाहरण था। यदि आप चाहते हैं तो आप _ की पहली घटना को occurr से बदल सकते हैं। तो "मछली और चिप्स_are_great" _ की पहली घटना को प्रतिस्थापित करने के लिए give के साथ "मछली और चिप्स_are_great" देगा, फिर ¬ ["मछली और चिप्स", "are_great" पाने के लिए se से विभाजित करें
sebjwallace

8

आप नियमित अभिव्यक्ति का उपयोग कर सकते हैं जैसे:

var arr = element.split(/_(.*)/)
आप दूसरे पैरामीटर का उपयोग कर सकते हैं जो विभाजन की सीमा को निर्दिष्ट करता है। अर्थात: var फ़ील्ड = element.split ('_', 1) [1];

6
यह केवल निर्दिष्ट करता है कि कितने विभाजित आइटम वापस किए जाते हैं, न कि कितनी बार विभाजित होते हैं। 'good_luck_buddy'.split('_', 1);रिटर्न सिर्फ['good']
एलेक्स विडाल

धन्यवाद ने उस पर एक धारणा बनाई। नियमित अभिव्यक्ति का उपयोग करने के लिए पोस्ट अपडेट करें।
चंदू

क्या (:?.*)गैर-कब्जा समूह होना चाहिए था? यदि ऐसा है, तो यह होना चाहिए (?:.*), लेकिन यदि आप इसे सही करते हैं तो आप पाएंगे कि यह किसी भी अधिक काम नहीं करता है। किसी भी वर्ण के शून्य या अधिक के बाद (:?.*)एक वैकल्पिक से मेल खाता है :। यह समाधान उसी कारण के लिए काम करना समाप्त करता है @ MarkF's करता है: पहली बार _टोकन सूची में जोड़े जाने के बाद सब कुछ क्योंकि यह एक कैप्चरिंग समूह में मिलान किया गया था। (इसके अलावा, gस्प्लिट रेगेक्स में उपयोग किए जाने पर संशोधक का कोई प्रभाव नहीं पड़ता है।)
एलन मूर

धन्यवाद, इसका एहसास नहीं हुआ। रेगेक्स को अद्यतित किया और इसे दो-दो स्थानों पर आजमाया ...
चंदू

1
यह ie8 में काम नहीं करता है और मैं वापस इंडेक्सऑफ और सबस्ट्रिंग में स्विच करता हूं
इगोर अलेक्सेव

5

आजकल String.prototype.splitवास्तव में आपको विभाजन की संख्या को सीमित करने की अनुमति देता है।

str.split([separator[, limit]])

...

वैकल्पिक सीमा

एक गैर-नकारात्मक पूर्णांक विभाजन की संख्या को सीमित करता है। यदि प्रदान किया जाता है, तो निर्दिष्ट विभाजक की प्रत्येक घटना पर स्ट्रिंग को विभाजित करता है, लेकिन जब सीमा प्रविष्टियां सरणी में रखी जाती हैं, तो रुक जाती हैं। किसी भी बचे हुए पाठ को सरणी में शामिल नहीं किया गया है।

सरणी में सीमा से कम प्रविष्टियाँ हो सकती हैं यदि सीमा समाप्त होने से पहले पहुँच जाती है। यदि सीमा 0 है, तो कोई विभाजन नहीं किया जाता है।

चेतावनी

यह आपके द्वारा अपेक्षित तरीके से काम नहीं कर सकता है। मैं उम्मीद कर रहा था कि यह बाकी सीमांकक की उपेक्षा करेगा, लेकिन इसके बजाय, जब यह सीमा तक पहुंचता है, तो यह शेष स्ट्रिंग को फिर से विभाजित करता है, वापसी परिणामों से विभाजन के बाद भाग को छोड़ देता है।

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C"]

मैं उम्मीद कर रहा था:

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B_C_D_E"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C_D_E"]

मुझे भी। PHP की तरह लगता है "पहले" और "बाकी" में विभाजित है।
बनानाएड

5

इस समाधान ने मेरे लिए काम किया

var str = "good_luck_buddy";
var index = str.indexOf('_');
var arr = [str.slice(0, index), str.slice(index + 1)];

//arr[0] = "good"
//arr[1] = "luck_buddy"

या

var str = "good_luck_buddy";
var index = str.indexOf('_');
var [first, second] = [str.slice(0, index), str.slice(index + 1)];

//first = "good"
//second = "luck_buddy"

हालांकि यह काम नहीं करता है यदि फाड़नेवाला में 1 से अधिक वर्ण हैं, हालांकि।
हयकम

4

जावास्क्रिप्ट का String.splitदुर्भाग्य से विभाजन की वास्तविक संख्या को सीमित करने का कोई तरीका नहीं है। इसका एक दूसरा तर्क है जो निर्दिष्ट करता है कि कितने वास्तविक विभाजन आइटम वापस आ गए हैं, जो आपके मामले में उपयोगी नहीं है। समाधान स्ट्रिंग को विभाजित करने के लिए होगा, पहले आइटम को शिफ्ट करें, फिर शेष वस्तुओं को फिर से जोड़ दें ::

var element = $(this).attr('class');
var parts = element.split('_');

parts.shift(); // removes the first item from the array
var field = parts.join('_');

मैं देख रहा हूं कि स्प्लिट फंक्शन मदद नहीं करता है, लेकिन रेगेक्स का उपयोग करने से यह प्राप्त होता है। यह निर्दिष्ट करना चाहिए कि आप स्प्लिट फ़ंक्शन को स्वयं, मूल रूप से संदर्भित कर रहे हैं।
डैन हैनली

1
दिलचस्प है, यह समाधान समस्या को अधिक पठनीय / प्रबंधनीय समाधान के लिए विचलित करता है। एक पूर्ण नाम को पहले और अंतिम में परिवर्तित करने के मेरे मामले में (हाँ हमारी आवश्यकताओं ने इस तर्क को मजबूर किया) इस समाधान ने सबसे अच्छा काम किया और अधिक पठनीय था फिर अन्य। धन्यवाद
Sukima

यह अब सच नहीं है :)
क्रैकेन

3

मुझे स्ट्रिंग के दो भागों की आवश्यकता है, इसलिए, रेगेक्स लुकबाइंड मेरी मदद करते हैं।

const full_name = 'Maria do Bairro';
const [first_name, last_name] = full_name.split(/(?<=^[^ ]+) /);
console.log(first_name);
console.log(last_name);


3

विनाशकारी असाइनमेंट की मदद से यह अधिक पठनीय हो सकता है:

let [first, ...rest] = "good_luck_buddy".split('_')
rest = rest.join('_')

2

सबसे तेज उपाय?

मैंने कुछ बेंचमार्क चलाए , और इस समाधान ने बेहद जीत हासिल की: 1

str.slice(str.indexOf(delim) + delim.length)

// as function
function gobbleStart(str, delim) {
    return str.slice(str.indexOf(delim) + delim.length);
}

// as polyfill
String.prototype.gobbleStart = function(delim) {
    return this.slice(this.indexOf(delim) + delim.length);
};

अन्य समाधानों के साथ प्रदर्शन की तुलना

केवल करीबी दावेदार कोड की एक ही पंक्ति थी, इसके substrबजाय उपयोग करने के अलावा slice

अन्य समाधान जिन्हें मैंने शामिल करने की कोशिश की splitया RegExpएक बड़ा प्रदर्शन हिट लिया और परिमाण धीमे होने के 2 आदेश थे । का प्रयोग joinके परिणामों पर split, ज़ाहिर है, एक अतिरिक्त प्रदर्शन जुर्माना कहते हैं।

वे धीमे क्यों हैं? किसी भी समय एक नई वस्तु या सरणी बनाई जानी चाहिए, जेएस को ओएस से मेमोरी का एक हिस्सा अनुरोध करना होगा। यह प्रक्रिया बहुत धीमी है।

यदि आप बेंचमार्क का पीछा कर रहे हैं, तो यहां कुछ सामान्य दिशानिर्देश दिए गए हैं:

  • वस्तुओं {}या सरणियों [](जैसे जो splitबनाता है) के लिए नया गतिशील मेमोरी आवंटन प्रदर्शन में बहुत अधिक खर्च करेगा।
  • RegExp खोज अधिक जटिल हैं और इसलिए स्ट्रिंग खोजों की तुलना में धीमी हैं।
  • यदि आपके पास पहले से ही एक सरणी है, तो विनाशकारी सरणियाँ लगभग उतनी ही तेजी से हैं जितना स्पष्ट रूप से उन्हें अनुक्रमणित करता है, और भयानक दिखता है।

पहले उदाहरण से परे हटना

यहाँ एक समाधान है कि nth उदाहरण के लिए और सहित टुकड़ा होगा। यह बहुत तेज़ नहीं है, लेकिन ओपी के सवाल पर, gobble(element, '_', 1)अभी भी> 2x एक RegExpया splitसमाधान से तेज है और अधिक कर सकता है:

/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
  let remain = limit;
  if (limit <= 0) { // set remain to count of delim - num to leave
    let i = 0;
    while (i < haystack.length) {
      const found = haystack.indexOf(needle, i);
      if (found === -1) {
        break;
      }
      remain++;
      i = found + needle.length;
    }
  }

  let i = 0;
  while (remain > 0) {
    const found = haystack.indexOf(needle, i);
    if (found === -1) {
      break;
    }
    remain--;
    i = found + needle.length;
  }
  return haystack.slice(i);
}

उपरोक्त परिभाषा के साथ, gobble('path/to/file.txt', '/')फ़ाइल का नाम देगा, और gobble('prefix_category_item', '_', 1)इस उत्तर में पहले समाधान की तरह उपसर्ग को हटा देगा।


  1. MacOSX 10.14 पर क्रोम 70.0.3538.110 में टेस्ट चलाए गए।

चलो ... यह 2019 है ... क्या लोग अभी भी इस तरह की चीज़ों को माइक्रोबेनमार्किंग कर रहे हैं?
विक्टर श्रोडर

मैं सहमत हूँ। यद्यपि माइक्रोबेनमार्किंग थोड़ा दिलचस्प है, आपको अनुकूलन के लिए एक संकलक या अनुवादक पर भरोसा करना चाहिए। जो जानता है। इसे पढ़ने वाला कोई व्यक्ति कंपाइलर का निर्माण कर रहा है या ejs / एम्बेडेड का उपयोग कर रहा है और रेगेक्स का उपयोग नहीं कर सकता है। हालांकि, यह एक रेगेक्स की तुलना में मेरे विशिष्ट मामले के लिए अच्छा लग रहा है। (मैं "सबसे तेज समाधान"
निकालूंगा

1

मार्क एफ का समाधान भयानक है लेकिन यह पुराने ब्राउज़रों द्वारा समर्थित नहीं है। केनेबेक का समाधान भयानक और पुराने ब्राउज़रों द्वारा समर्थित है, लेकिन रेगेक्स का समर्थन नहीं करता है।

इसलिए, यदि आप एक समाधान की तलाश कर रहे हैं जो केवल एक बार आपकी स्ट्रिंग को विभाजित करता है, जो पुराने ब्राउज़रों द्वारा समर्थित है और रेगेक्स का समर्थन करता है, तो यहां मेरा समाधान है:

String.prototype.splitOnce = function(regex)
{
    var match = this.match(regex);
    if(match)
    {
        var match_i = this.indexOf(match[0]);
        
        return [this.substring(0, match_i),
        this.substring(match_i + match[0].length)];
    }
    else
    { return [this, ""]; }
}

var str = "something/////another thing///again";

alert(str.splitOnce(/\/+/)[1]);


1

मेरे जैसे शुरुआती लोगों के लिए जो नियमित अभिव्यक्ति के अभ्यस्त नहीं हैं, इस समाधान समाधान ने काम किया:

   var field = "Good_Luck_Buddy";
   var newString = field.slice( field.indexOf("_")+1 );

स्लाइस () विधि एक स्ट्रिंग का एक हिस्सा निकालती है और एक नया स्ट्रिंग लौटाती है और indexOf () विधि एक स्ट्रिंग में निर्दिष्ट मान के पहले पाए जाने की स्थिति को लौटाती है।


यह एक वर्कअराउंड नहीं है, बल्कि इसे करने का एक उचित तरीका है;)
विक्टर श्रोडर

1

replace()एक रेगेक्स के साथ स्ट्रिंग विधि का उपयोग करें :

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);

इस regex पहले से पहले 0 या अधिक से मेल खाता है _, और _अपने आप में। मैच को एक खाली स्ट्रिंग द्वारा बदल दिया जाता है।


यहां का document.body.innerHTMLहिस्सा पूरी तरह से बेकार है।
विक्टर श्रोडर

@ VictorSchröder आप बिना स्निपेट के आउटपुट को देखने की उम्मीद कैसे करते हैं document.body.innerHTML?
जेम्स टी

1
document.bodyडोम पर मौजूद होना निर्भर करता है और यह शुद्ध जावास्क्रिप्ट वातावरण पर काम नहीं करेगा। console.logइस उद्देश्य के लिए पर्याप्त है या केवल निरीक्षण के लिए एक चर में परिणाम छोड़ दें।
विक्टर श्रोडर

@ VictorSchröder मुझे नहीं लगता कि इससे बहुत भ्रम हुआ होगा, लेकिन फिर भी मैंने संपादित किया है।
जेम्स टी।

0

इसने मेरे लिए Chrome + FF पर काम किया:

"foo=bar=beer".split(/^[^=]+=/)[1] // "bar=beer"
"foo==".split(/^[^=]+=/)[1] // "="
"foo=".split(/^[^=]+=/)[1] // ""
"foo".split(/^[^=]+=/)[1] // undefined

यदि आपको भी कुंजी की आवश्यकता है तो यह कोशिश करें:

"foo=bar=beer".split(/^([^=]+)=/) // Array [ "", "foo", "bar=beer" ]
"foo==".split(/^([^=]+)=/) // [ "", "foo", "=" ]
"foo=".split(/^([^=]+)=/) // [ "", "foo", "" ]
"foo".split(/^([^=]+)=/) // [ "foo" ]

//[0] = ignored (holds the string when there's no =, empty otherwise)
//[1] = hold the key (if any)
//[2] = hold the value (if any)

0

यहाँ एक RegExp है जो चाल करता है।

'good_luck_buddy' . split(/^.*?_/)[1] 

पहले यह मैच को '^' से शुरू करने के लिए मजबूर करता है। फिर यह किसी भी ऐसे वर्ण से मेल खाता है जो '_' नहीं है, दूसरे शब्दों में पहले '_' से पहले सभी वर्ण।

'?' का अर्थ है कि पूरे पैटर्न का मिलान करने वाले वर्णों की न्यूनतम संख्या '*।'? क्योंकि यह '_' द्वारा पीछा किया जाता है, जो तब मैच में अपने अंतिम चरित्र के रूप में शामिल होता है।

इसलिए यह विभाजन () इस तरह के मिलान वाले हिस्से को अपने 'स्प्लिटर' के रूप में उपयोग करता है और इसे परिणामों से हटा देता है। इसलिए यह पहले '_' सहित सभी चीजों को हटा देता है और आपको परिणाम के 2 तत्व के रूप में बाकी देता है। पहला तत्व "" मिलान वाले भाग से पहले के भाग का प्रतिनिधित्व करता है। यह "" है क्योंकि मैच शुरू से शुरू होता है।

अन्य RegExps हैं जो पिछले उत्तर में चंदू द्वारा दिए गए /_(.*)/ की तरह काम करते हैं।

/^.*?_/ का लाभ यह है कि आप समझ सकते हैं कि विशेष भूमिका के बारे में पता किए बिना वह क्या करता है जो समूहों को प्रतिस्थापित करने के साथ खेलते हैं ()।

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