जब पायथन में एक खाली स्ट्रिंग को विभाजित करते हैं, तो विभाजन () विभाजन के दौरान खाली सूची क्यों लौटती है ('\ n') [[]]?


155

मैं split('\n')एक स्ट्रिंग में लाइनें प्राप्त करने के लिए उपयोग कर रहा हूं , और पाया कि ''.split()रिटर्न []करते समय एक खाली सूची ''.split('\n')देता है ['']। क्या इस तरह के अंतर का कोई विशेष कारण है?

और क्या किसी स्ट्रिंग में लाइनों को गिनने का कोई और सुविधाजनक तरीका है?


जवाबों:


247

प्रश्न: मैं एक स्ट्रिंग में लाइनें प्राप्त करने के लिए विभाजन ('\ n') का उपयोग कर रहा हूं, और पाया कि '' .plplit () खाली सूची [] लौटाता है, जबकि '' .split ('\ n') रिटर्न [''] ।

Str.split () विधि दो एल्गोरिदम है। यदि कोई तर्क नहीं दिया जाता है, तो यह व्हाट्सएप के दोहराया रनों पर विभाजित होता है। हालाँकि, यदि कोई तर्क दिया जाता है, तो इसे एक एकल सीमांकक के रूप में माना जाता है जिसमें बार-बार रन नहीं होते हैं।

खाली स्ट्रिंग को विभाजित करने के मामले में, पहला मोड (कोई तर्क नहीं) एक खाली सूची लौटाएगा क्योंकि व्हॉट्सएप खाया जाता है और परिणाम सूची में डालने के लिए कोई मूल्य नहीं हैं।

इसके विपरीत, दूसरा मोड (जैसे एक तर्क के साथ \n) पहले खाली क्षेत्र का उत्पादन करेगा। विचार करें कि क्या आपने लिखा था '\n'.split('\n'), तो आपको दो फ़ील्ड मिलेंगे (एक विभाजन, आपको दो हिस्से देता है)।

प्रश्न: क्या इस तरह के अंतर का कोई विशेष कारण है?

यह पहला मोड उपयोगी है जब डेटा को व्हॉट्सएप की परिवर्तनीय मात्रा वाले कॉलम में संरेखित किया जाता है। उदाहरण के लिए:

>>> data = '''\
Shasta      California     14,200
McKinley    Alaska         20,300
Fuji        Japan          12,400
'''
>>> for line in data.splitlines():
        print line.split()

['Shasta', 'California', '14,200']
['McKinley', 'Alaska', '20,300']
['Fuji', 'Japan', '12,400']

दूसरा मोड सीमांकित डेटा जैसे कि CSV के लिए उपयोगी है जहां बार-बार अल्पविराम खाली क्षेत्रों को दर्शाता है। उदाहरण के लिए:

>>> data = '''\
Guido,BDFL,,Amsterdam
Barry,FLUFL,,USA
Tim,,,USA
'''
>>> for line in data.splitlines():
        print line.split(',')

['Guido', 'BDFL', '', 'Amsterdam']
['Barry', 'FLUFL', '', 'USA']
['Tim', '', '', 'USA']

ध्यान दें, परिणाम फ़ील्ड की संख्या सीमांकक की संख्या से अधिक है। रस्सी काटने की सोचो। यदि आप कोई कटौती नहीं करते हैं, तो आपके पास एक टुकड़ा है। एक कट कर, दो टुकड़े देता है। दो कट बनाते हैं, तीन टुकड़े करते हैं। और इसलिए यह पायथन के str.split (सीमांकक) विधि के साथ है:

>>> ''.split(',')       # No cuts
['']
>>> ','.split(',')      # One cut
['', '']
>>> ',,'.split(',')     # Two cuts
['', '', '']

प्रश्न: और क्या किसी स्ट्रिंग में लाइनों को गिनने का कोई और सुविधाजनक तरीका है?

हां, कुछ आसान तरीके हैं। एक str.count () का उपयोग करता है और दूसरा str.splitlines () का उपयोग करता है । दोनों तरह से एक ही जवाब देंगे जब तक कि अंतिम लाइन गायब न हो \n। यदि अंतिम न्यूलाइन गायब है, तो str.splitlines दृष्टिकोण सटीक उत्तर देगा। एक तेज़ तकनीक जो सटीक भी है, गिनती पद्धति का उपयोग करती है लेकिन फिर इसे अंतिम न्यूलाइन के लिए सही करती है:

>>> data = '''\
Line 1
Line 2
Line 3
Line 4'''

>>> data.count('\n')                               # Inaccurate
3
>>> len(data.splitlines())                         # Accurate, but slow
4
>>> data.count('\n') + (not data.endswith('\n'))   # Accurate and fast
4    

@ काज से प्रश्न: एक ही फ़ंक्शन में बिल्ली को दो अलग-अलग एल्गोरिदम जूता-सींग क्यों दिया जाता है?

Str.split के लिए हस्ताक्षर लगभग 20 साल पुराना है, और उस युग के कई एपीआई सख्ती से व्यावहारिक हैं। सही नहीं है, विधि हस्ताक्षर या तो "भयानक" नहीं है। अधिकांश भाग के लिए, गुइडो के एपीआई डिजाइन विकल्प समय की कसौटी पर खरे उतरे हैं।

वर्तमान एपीआई फायदे के बिना नहीं है। स्ट्रिंग पर विचार करें जैसे:

ps_aux_header  = "USER               PID  %CPU %MEM      VSZ"
patient_header = "name,age,height,weight"

जब इन तारों को खेतों में तोड़ने के लिए कहा जाता है, तो लोग एक ही अंग्रेजी शब्द "स्प्लिट" का उपयोग करते हुए दोनों का वर्णन करते हैं। जब fields = line.split() या जैसे कोड को पढ़ने के लिए कहा जाता है fields = line.split(','), तो लोग "क्षेत्रों में एक रेखा को विभाजित करते हैं" जैसे कथनों की सही व्याख्या करते हैं।

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


28

यह बस प्रलेखन के अनुसार काम करने वाला माना जाता है :

एक निर्दिष्ट विभाजक रिटर्न के साथ एक खाली स्ट्रिंग को विभाजित करना ['']

अगर sep निर्दिष्ट नहीं है या कोई भी नहीं है, तो एक अलग विभाजन एल्गोरिथ्म लागू किया जाता है: लगातार व्हाट्सएप के रन को एक एकल विभाजक के रूप में माना जाता है, और यदि स्ट्रिंग में अग्रणी या अनुगामी व्हाट्सएप है, तो परिणाम प्रारंभ या अंत में कोई खाली स्ट्रिंग नहीं होगा। नतीजतन, एक खाली स्ट्रिंग या एक स्ट्रिंग को विभाजित करना जिसमें कोई भी विभाजक रिटर्न के साथ सिर्फ व्हाट्सएप शामिल है []।

इसलिए, इसे स्पष्ट करने के लिए, split()फ़ंक्शन दो अलग-अलग विभाजन एल्गोरिदम को लागू करता है, और यह तय करने के लिए एक तर्क की उपस्थिति का उपयोग करता है कि कौन सा चलना है। यह हो सकता है क्योंकि यह तर्क के साथ एक से अधिक तर्क के लिए किसी को अनुकूलित करने की अनुमति देता है; मुझे नहीं पता।


4

.split()बिना मापदंडों के चालाक होने की कोशिश करता है। यह किसी भी व्हाट्सएप, टैब, स्पेस, लाइन फीड आदि पर विभाजन करता है, और इसके परिणामस्वरूप सभी खाली स्ट्रिंग्स को भी छोड़ देता है।

>>> "  fii    fbar \n bopp ".split()
['fii', 'fbar', 'bopp']

अनिवार्य रूप से, .split()मापदंडों के बिना एक स्ट्रिंग से शब्दों को निकालने के लिए उपयोग किया जाता है, .split()मापदंडों के विपरीत जो बस एक स्ट्रिंग लेता है और इसे विभाजित करता है।

यही अंतर का कारण है।

और हाँ, विभाजित करके लाइनों की गिनती एक कुशल तरीका नहीं है। पंक्ति फ़ीड की संख्या की गणना करें, और एक को जोड़ें यदि स्ट्रिंग एक पंक्ति फ़ीड के साथ समाप्त नहीं होती है।


2

उपयोग करें count():

s = "Line 1\nLine2\nLine3"
n_lines = s.count('\n') + 1

4
+ 1 केवल तभी किया जाना चाहिए जब पाठ '\ n' के साथ समाप्त न हो।
लेन्नर्ट रेग्रोब

8
ठीक है, अगर यह "\ n" के साथ समाप्त होता है तो अंतिम पंक्ति एक खाली रेखा है। हालांकि बेकार, यह अभी भी लाइन के रूप में गिना जाता है, नहीं?
जैकब एम।

2
नहीं। जब मैं किसी फ़ाइल में पाठ की 3 पंक्तियाँ लिखता हूँ और उनमें से प्रत्येक को एक पंक्ति-पंक्ति के साथ समाप्त करता हूँ, तो मैं कहूँगा कि फ़ाइल में 3 पंक्तियाँ हैं। यूनिक्स पर एक पाठ फ़ाइल को हमेशा लाइनफीड के साथ समाप्त करना सबसे अच्छा अभ्यास है। अन्यथा cat fileआपकी कमांड लाइन को तोड़ देता है और तोड़फोड़ की शिकायत करता है। vi हमेशा एक को जोड़ते हैं।
user829755

2
>>> print str.split.__doc__
S.split([sep [,maxsplit]]) -> list of strings

Return a list of the words in the string S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.

अंतिम वाक्य पर ध्यान दें।

लाइनों को गिनने के लिए आप बस यह गिन सकते \nहैं कि कितने हैं:

line_count = some_string.count('\n') + some_string[-1] != '\n'

अंतिम भाग अंतिम पंक्ति को ध्यान में रखता है, जो इसके साथ समाप्त नहीं होता है \n, भले ही इसका मतलब यह है कि Hello, World!और Hello, World!\nउसी पंक्ति की गणना है (जो मेरे लिए उचित है), अन्यथा आप बस 1की गिनती में जोड़ सकते हैं \n


0

लाइनों को गिनने के लिए, आप लाइन ब्रेक की संख्या को गिन सकते हैं:

n_lines = sum(1 for s in the_string if s == "\n") + 1 # add 1 for last line

संपादित करें :

बिल्ट-इन के साथ अन्य उत्तरcount अधिक उपयुक्त है, वास्तव में


3
केवल उपयोग करने के अलावा count, बूल जोड़ने योग्य हैं (वास्तव में, वे उपवर्ग int), इसलिए जीनएक्सपी के रूप में लिखा जा सकता है sum(s == "\n" for s in the_string)
LVC

अभी आप केवल खाली लाइनों की गिनती कर रहे हैं?
थाइज वैन दीने

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