एक खाली स्ट्रिंग पर "विभाजित" एक गैर-रिक्त सरणी क्यों लौटाता है?


111

खाली स्ट्रिंग पर विभाजित आकार 1 की एक सरणी देता है:

scala> "".split(',')
res1: Array[String] = Array("")

विचार करें कि यह खाली सरणी देता है:

scala> ",,,,".split(',')
res2: Array[String] = Array()

कृपया समझाएँ :)


5
इसके अतिरिक्त, यह व्यवहार के साथ असंगत लगता है जब स्ट्रिंग में विभाजक का केवल एक उदाहरण होता है। इस मामले में परिणाम प्रभावी रूप से एक खाली सरणी है: ","। विभाजन (",")। लंबाई == 0
एलडी।

जवाबों:


37

उसी कारण से

",test" split ','

तथा

",test," split ','

आकार की एक सरणी वापस आ जाएगी। पहले मैच से पहले सब कुछ पहले तत्व के रूप में वापस आ गया है।


5
खाली स्ट्रिंग एक स्ट्रिंग है, कुछ भी नहीं। (कहीं भी लेकिन एक्सेल में)
राफेल

5
@ राफेल या ओरेकल डेटाबेस में
ऑस्टिन

7
@Raphael, किसी भी अन्य प्रोग्रामिंग भाषा में "".split("wtf").lengthरिटर्न 0. केवल जे एस में यह 1.: /
एंड्री Mikhaylov - lolmaus

11
@ डैनियल सी.सोबरल ओके, तो "," split ","0 की सरणी क्यों देता है?
जोन

5
आखिरी मैच के बाद भी सब कुछ क्यों नहीं हुआ?
डिडिएर ए।

72

यदि आप एक नारंगी शून्य बार विभाजित करते हैं, तो आपके पास बिल्कुल एक टुकड़ा है - नारंगी।


8
लेकिन नारंगी खाली नहीं है (आइडीके अगर ऑलूस का मतलब क्या है), इसका नारंगी। शायद एक नारंगी को विभाजित करना जो वहां होना चाहिए, लेकिन ऐसा नहीं है, इसलिए आपको एक ही मूल्य वापस मिलता है: एक खाली स्थान xD
निक रोलैंडो

8
यह एक गहरी बातचीत है।

31
यह रूपक के लिए समझ में आता है "orange".split(','), लेकिन खाली तारों को विभाजित करने के लिए स्पष्ट रूप से प्रासंगिक नहीं है। यदि मैं अपनी कमी को नारंगी शून्य बार विभाजित करता हूं, तो मेरे पास अभी भी नारंगी नहीं है; क्या हम इस बात का प्रतिनिधित्व करते हैं कि संतरे की एक खाली सूची के रूप में, बिल्कुल एक संतरे की एक सूची, बारह संतरे की सूची, या क्या? यह सवाल नहीं है कि हम क्या करते हैं, बल्कि हम इसका प्रतिनिधित्व कैसे करते हैं।
माचिस

1
लेकिन अगर आप किसी गैर-मौजूद किताब को उसके पन्नों से अलग करते हैं, तो आपको कुछ नहीं मिलेगा।
15

49

जावा और स्काला स्प्लिट मेथड इस तरह दो चरणों में काम करते हैं:

  • सबसे पहले, स्ट्रिंग को सीमांकक द्वारा विभाजित करें। प्राकृतिक परिणाम यह है कि यदि स्ट्रिंग में सीमांकक नहीं है, तो एक सिंगलटन सरणी जिसमें केवल इनपुट स्ट्रिंग है, वापस आ गया है,
  • दूसरा, सभी सही खाली तारों को हटा दें। यही कारण है कि ",,,".split(",")खाली सरणी देता है।

इसके अनुसार, "".split(",")दूसरे चरण के कारण रिक्त सरणी का परिणाम होना चाहिए, है ना?

यह होना चाहिए। दुर्भाग्य से, यह एक कृत्रिम रूप से शुरू किया गया कोने का मामला है। और यह बुरा है, लेकिन कम से कम इसे प्रलेखित किया जाता है java.util.regex.Pattern, अगर आपको प्रलेखन पर एक नज़र रखना याद है:

N == 0 के लिए, परिणाम n <0 के लिए है, इसके अलावा खाली तारों को पीछे नहीं लौटाया जाएगा। (ध्यान दें कि जहां इनपुट स्वयं एक रिक्त स्ट्रिंग है, विशेष है, जैसा कि ऊपर वर्णित है, और सीमा पैरामीटर वहां लागू नहीं होता है।)

समाधान 1: हमेशा दूसरे पैरामीटर के रूप में -1 पास करें

इसलिए, मैं आपको सलाह देता हूं कि आप हमेशा n == -1दूसरे पैरामीटर के रूप में पास करें (यह चरण दो को ऊपर छोड़ देगा), जब तक कि आप विशेष रूप से नहीं जानते कि आप क्या हासिल करना चाहते हैं / आप सुनिश्चित हैं कि खाली स्ट्रिंग कुछ ऐसा नहीं है जो आपके प्रोग्राम को इनपुट के रूप में मिलेगा।

समाधान 2: अमरूद फाड़नेवाला वर्ग का उपयोग करें

यदि आप पहले से ही अपनी परियोजना में अमरूद का उपयोग कर रहे हैं, तो आप स्प्लिटर (प्रलेखन) वर्ग का प्रयास कर सकते हैं । इसकी एक बहुत समृद्ध एपीआई है, और यह आपके कोड को समझने में बहुत आसान बनाता है।

Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"

1
+1, यह एकमात्र उत्तर है जो वास्तव में प्रलेखन का हवाला देता है और बताता है कि यह असंगत है। हालांकि, मुझे अपने जावाडॉक में टिप्पणी का हाइलाइटेड हिस्सा नहीं मिला।
योगू

मैंने इसे java.util.regex.Pattern में पाया है, लेकिन ऐसा लगता है कि ज्यादातर चला गया है। लेखन के समय, यह निश्चित रूप से आधिकारिक OpenJDK स्रोत वृक्ष में एक जावाडॉक के रूप में मौजूद था। android.googlesource.com/platform/libcore/+/… शायद हमें बग की रिपोर्ट करनी चाहिए?
रोक क्राल

बग की रिपोर्ट करने के लिए एक अच्छा विचार होगा - व्यवहार निश्चित रूप से बदला नहीं जाएगा, लेकिन इसे कम से कम दस्तावेज होना चाहिए।
योगू

@RokKralj Android ने OpenJDK लाइब्रेरी का उपयोग नहीं किया, लेकिन इसके बजाय Apache सद्भाव पर आधारित था, इसलिए शायद आप गलत जगह देख रहे हैं?
17

1
"".split (",", n)Oracle JDK 8 के साथ n (-1, 0, 1) के लिए एक तत्व एरे को उत्पन्न करता है। केवल नॉन-खाली टोकन की एक सूची प्राप्त करना अच्छा होगा - लगता है कि पूर्ण रेगेक्स आवश्यक हो सकता है (कुछ ऐसा "[^,\\s]+[^,]*[^,\\s]*")।
simon.watts

40

खाली स्ट्रिंग को विभाजित करने से पहला तत्व के रूप में खाली स्ट्रिंग वापस आ जाता है। यदि लक्ष्य स्ट्रिंग में कोई सीमांकक नहीं पाया जाता है, तो आपको आकार 1 की एक सरणी मिलेगी जो मूल स्ट्रिंग को पकड़े हुए है, भले ही वह खाली हो।


2
गलत। स्प्लिट सभी सही खाली स्ट्रिंग्स को निकालता है, इसलिए परिणाम एक खाली सरणी होना चाहिए। मेरा जवाब देखिए। ",".split(",")खाली सरणी देता है।
रोक क्राल

23

"a".split(",")-> "a" इसलिए "".split(",")->""


6
गलत। स्प्लिट सभी सही खाली स्ट्रिंग्स को निकालता है, इसलिए परिणाम एक खाली सरणी होना चाहिए। मेरा जवाब देखिए। ",".split(",")खाली सरणी देता है।
रोक क्राल

5

सभी प्रोग्रामिंग भाषाओं में मुझे पता है कि एक रिक्त स्ट्रिंग अभी भी एक मान्य स्ट्रिंग है। तो किसी भी सीमांकक का उपयोग करके एक विभाजन करना हमेशा एक तत्व सरणी को वापस करेगा जहां वह तत्व रिक्त स्ट्रिंग है। यदि यह एक शून्य (रिक्त नहीं) स्ट्रिंग था, तो यह एक अलग मुद्दा होगा।


मुझे लगता है कि यह एक पुस्तकालय समारोह है और भाषा का हिस्सा नहीं है। उदाहरण के लिए Google अमरूद में आप खाली तारों को छोड़ सकते हैं। > Iterable <string> pieces = com.google.common.base.Splitter.on (',') omitEmptyStrings ()। विभाजन ("");
जैतून

2

यह splitव्यवहार जावा से विरासत में मिला है, बेहतर या बदतर के लिए ...
स्कैम Stringआदिम से परिभाषा को ओवरराइड नहीं करता है ।

ध्यान दें, कि आप व्यवहार को संशोधित करने के लिए limitतर्क का उपयोग कर सकते हैं :

सीमा पैरामीटर पैटर्न लागू होने की संख्या को नियंत्रित करता है और इसलिए परिणामी सरणी की लंबाई को प्रभावित करता है। यदि सीमा n शून्य से अधिक है, तो पैटर्न को अधिकतम n - 1 बार लागू किया जाएगा, सरणी की लंबाई n से अधिक नहीं होगी, और सरणी की अंतिम प्रविष्टि में अंतिम मिलान किए गए सीमांकक से परे सभी इनपुट होंगे। यदि n गैर-सकारात्मक है, तो पैटर्न को यथासंभव कई बार लागू किया जाएगा और सरणी में कोई भी लंबाई हो सकती है। यदि n शून्य है, तो पैटर्न को यथासंभव कई बार लागू किया जाएगा, सरणी में कोई भी लंबाई हो सकती है, और खाली तारों को पीछे छोड़ दिया जाएगा।

अर्थात आप limit=-1(सभी?) अन्य भाषाओं के व्यवहार को प्राप्त करने के लिए सेट कर सकते हैं:

@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")

@ ",a,,b,,".split(",", -1)  // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")

ऐसा प्रतीत होता है कि जावा व्यवहार काफी भ्रामक है, लेकिन:

उपरोक्त व्यवहार कम से कम जावा 5 से जावा 8 तक देखा जा सकता है।

JDK-6559590 में एक खाली स्ट्रिंग को विभाजित करते समय खाली सरणी को वापस करने के लिए व्यवहार को बदलने का प्रयास किया गया था । हालाँकि, इसे जल्द ही JDK-8028321 में बदल दिया गया जब यह विभिन्न स्थानों में प्रतिगमन का कारण बनता है। परिवर्तन इसे प्रारंभिक जावा 8 रिलीज़ में कभी नहीं बनाता है।

नोट: विभाजन विधि शुरुआत से जावा में नहीं थी (यह 1.0.2 में नहीं है ) लेकिन वास्तव में कम से कम 1.4 (जैसे JSR51 लगभग 2002) देखें। मैं अभी भी जांच कर रहा हूं ...

यह स्पष्ट नहीं है कि जावा ने इसे पहले स्थान पर क्यों चुना (मेरा संदेह यह है कि यह मूल रूप से एक "किनारे मामले" में एक ओवरसाइट / बग था), लेकिन अब वास्तव में भाषा में बेक किया गया है और इसलिए यह बना हुआ है


मुझे यकीन नहीं है कि यह सवाल का जवाब देता है - जबकि यह यहां दिए गए उदाहरण के लिए सही हो सकता है, यह खाली स्ट्रिंग के मामले में मदद नहीं करता है - फिर "".split(",")भी एक एकल तत्व सरणी देता है [""]
डेव्यूडेवडे

@DaveyDaveDave जो हर दूसरी भाषा का अपेक्षित व्यवहार है। ",,,," स्काला में विचित्र / अलग व्यवहार है, और "" मामले से अलग है।
एंडी हेडन

0

स्ट्रिंग को विभाजित करते समय खाली स्ट्रिंग की कोई विशेष स्थिति नहीं है। तुम उपयोग कर सकते हो:

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.