পাইথনে একটি খালি স্ট্রিং বিভক্ত করার সময়, বিভাজন () বিভক্ত ('\ n') ফিরে আসার পরে খালি তালিকা কেন দেয় ['']?


154

আমি split('\n')এক স্ট্রিংয়ে লাইন পেতে ব্যবহার করছি এবং খুঁজে পেয়েছি যে ''.split()খালি তালিকা দেয় [], যখন ''.split('\n')ফিরে আসে ['']। এরকম পার্থক্যের কোনও নির্দিষ্ট কারণ আছে কি?

এবং স্ট্রিংয়ে লাইনগুলি গণনা করার আরও কোনও সুবিধাজনক উপায় নেই?


উত্তর:


247

প্রশ্ন: আমি এক স্ট্রিংয়ে লাইন পেতে স্প্লিট ('\ n') ব্যবহার করছি এবং দেখতে পেয়েছি যে '' .স্প্লিট () খালি তালিকা ফিরে আসে [], যখন '' .স্প্লিট ('\ 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']

দ্বিতীয় মোডটি সিএসভি-র মতো সীমিত তথ্যের জন্য দরকারী যেখানে বার বার কমা খালি ক্ষেত্রকে বোঝায়। উদাহরণ স্বরূপ:

>>> 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']

দ্রষ্টব্য, ফলাফলের ক্ষেত্রগুলির সংখ্যা প্রেরণকারীর সংখ্যার চেয়ে একটি বেশি। দড়ি কাটার কথা ভাবুন। আপনি যদি কোনও কাট না করেন তবে আপনার একটি টুকরা রয়েছে। একটি কাটা তৈরি, দুটি টুকরা দেয়। দুটি কাটা করা, তিন টুকরা দেয়। এবং তাই এটি পাইথনের স্ট্রিয়রস্প্লিট (ডিলিমিটার) পদ্ধতির সাথে:

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

প্রশ্ন: এবং স্ট্রিংয়ে লাইন গণনা করার আরও কোনও সুবিধাজনক উপায় নেই?

হ্যাঁ, কয়েকটি সহজ উপায় আছে। এর মধ্যে একটি স্ট্রকাউন্ট () এবং অন্যটি স্ট্রিংস্প্লিটলাইন () ব্যবহার করে । চূড়ান্ত লাইনটি অনুপস্থিত না হলে উভয় উপায়ে একই উত্তর দেবে \n। যদি চূড়ান্ত নিউলাইনটি অনুপস্থিত থাকে তবে স্ট্রিমস্প্লিটলাইনগুলি সঠিক উত্তর দেবে। একটি দ্রুত প্রযুক্তি যা সঠিক তা গণনা পদ্ধতি ব্যবহার করে তবে চূড়ান্ত নিউলাইনের জন্য এটি সংশোধন করে:

>>> 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

ডকুমেন্টেশন অনুসারে এটি কেবল কাজ করার কথা বলে মনে হয় :

একটি নির্দিষ্ট বিভাজক ফেরতের সাথে একটি খালি স্ট্রিং বিভক্ত করা ['']

যদি সেপ সুনির্দিষ্ট না হয় বা কোনও হয় না, একটি পৃথক বিভাজনযুক্ত অ্যালগরিদম প্রয়োগ করা হয়: পরপর শ্বেত স্পেসের রানগুলি একক বিভাজক হিসাবে বিবেচিত হয়, এবং স্ট্রিংটির নেতৃত্বাধীন বা পেছনের সাদা অংশ থাকলে ফলাফলের শুরু বা শেষের কোনও খালি স্ট্রিং থাকবে না। ফলস্বরূপ, খালি স্ট্রিং বা কেবল কোনও শ্বেত স্পেস সমন্বিত একটি স্ট্রিং বিভক্তকরণের সাথে কোনওটি বিভাজক ফিরে আসে না []।

সুতরাং, এটি পরিষ্কার করার জন্য, 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
পাঠ্যটি '\ n' দিয়ে শেষ না হলেই +1 করা উচিত।
লেনার্ট রেজেব্রো

8
ঠিক আছে, যদি এটি "\ n" দিয়ে শেষ হয় তবে শেষ লাইনটি খালি লাইন। যদিও অকেজো, এটি এখনও লাইন হিসাবে গণনা, না?
জাকব এম এম

2
কোন। আমি যখন কোনও ফাইলে 3 লাইনের পাঠ্য লিখি এবং সেগুলির প্রতিটি লাইনফিড দিয়ে শেষ করি, তখন আমি বলব যে ফাইলটিতে 3 টি লাইন রয়েছে। ইউনিক্সে একটি পাঠ্য ফাইল সর্বদা একটি লাইনফিডের সাথে শেষ করা ভাল অনুশীলন। অন্যথায় cat fileআপনার কমান্ড লাইন এবং subversion অভিযোগ গারবলস। vi সবসময় একটি সংযোজন।
ব্যবহারকারী 829755

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

এই মুহূর্তে আপনি কেবল খালি রেখা গণনা করছেন?
থিজ ভ্যান ডিয়েন

হ্যাঁ, আমি কোনও খালি লাইনগুলি বাতিল করি না
জাকুব এম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.