বড় হাতের অক্ষরে একটি স্ট্রিং বিভক্ত করুন


100

প্রদত্ত অক্ষরের সংকলনের উপস্থিতির আগে একটি স্ট্রিংকে বিভক্ত করার অজগরটি কী ?

উদাহরণস্বরূপ, আমি 'TheLongAndWindingRoad' বড় হাতের অক্ষরের যে কোনও সংগে বিভাজন করতে চাই (সম্ভবত প্রথমটি বাদে সম্ভবত) এবং পেতে পারি ['The', 'Long', 'And', 'Winding', 'Road']

সম্পাদনা করুন: এটি একক সংঘটনগুলিও বিভক্ত করা উচিত, অর্থাত্ 'ABC'আমি যা পেতে চাই ['A', 'B', 'C']

উত্তর:


142

দুর্ভাগ্যক্রমে পাইথনের শূন্য প্রস্থের ম্যাচে বিভাজন সম্ভব নয় । তবে আপনি এর re.findallপরিবর্তে ব্যবহার করতে পারেন :

>>> import re
>>> re.findall('[A-Z][^A-Z]*', 'TheLongAndWindingRoad')
['The', 'Long', 'And', 'Winding', 'Road']
>>> re.findall('[A-Z][^A-Z]*', 'ABC')
['A', 'B', 'C']

14
সাবধান হোন যে এটি প্রথম মূল চরিত্রের আগে কোনও অক্ষর ফেলে ফেলবে। 'দ্য লংএন্ড উইন্ডিংরোড'-এর ফলাফল [' লং ',' এবং ',' উইন্ডিং ',' রোড ']
নেবে

15
@ মার্কশুল্ডার: আপনার যদি এই ক্ষেত্রে প্রয়োজন '[a-zA-Z][^A-Z]*'হয় তবে কেবল রেজেক্স হিসাবে ব্যবহার করুন।
নুব

আপারকেস না করে কি একই কাজ করা সম্ভব?
লরেন্ট সিজারো

4
নিম্ন উটের মামলার শব্দগুলি বিভক্ত করার জন্যprint(re.findall('^[a-z]+|[A-Z][^A-Z]*', 'theLongAndWindingRoad'))
হার্ড_কর্মিং_আর

35

এখানে একটি বিকল্প রেজেক্স সমাধান is সমস্যাটি "আবার বিভাজন করার আগে প্রতিটি বড় হাতের অক্ষরের আগে একটি স্থান কীভাবে সন্নিবেশ করবো" হিসাবে আবারও চিহ্নিত করা যায়:

>>> s = "TheLongAndWindingRoad ABC A123B45"
>>> re.sub( r"([A-Z])", r" \1", s).split()
['The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']

এর মধ্যে সমস্ত অ-শ্বেতস্পেস অক্ষর সংরক্ষণ করার সুবিধা রয়েছে যা অন্যান্য বেশিরভাগ সমাধানে দেয় না।


আপনি দয়া করে ব্যাখ্যা করতে পারেন কেন জায়গাটি \ 1 এর আগে কাজ করে? এটি কি বিভক্ত পদ্ধতির কারণে বা এটি রেজেক্সের সাথে সম্পর্কিত কিছু?
লক্ষ_সাম

যে কোনও সাদা স্পেস স্ট্রিংয়ের মধ্যে ডিলিমিটার ডিফল্টগুলি বিভক্ত করুন
সিআইফোর্ডকুকিজ

@ ল্যাক্স_সাম রেজেক্স বিকল্পটি যে কোনও মূলধনের আগে কেবল একটি স্থান যুক্ত করে এবং বিভক্ত () এটি তুলে নিয়ে যায়
প্রাণবন্ত

20
>>> import re
>>> re.findall('[A-Z][a-z]*', 'TheLongAndWindingRoad')
['The', 'Long', 'And', 'Winding', 'Road']

>>> re.findall('[A-Z][a-z]*', 'SplitAString')
['Split', 'A', 'String']

>>> re.findall('[A-Z][a-z]*', 'ABC')
['A', 'B', 'C']

আপনি যদি "It'sATest"ভাগ করতে চান ["It's", 'A', 'Test']তবে এটিকে পুনরায় পরিবর্তন করতে"[A-Z][a-z']*"


+1: প্রথমত এবিসি কাজ করার জন্য। আমি এখন আমার উত্তর আপডেট করেছি।
মার্ক বাইয়ার্স

>>> পুনঃফিন্ডাল ('[এজেড] [এজে] *', "এটি অর্থনীতির প্রায় 70%") -----> ['এটি', 'অর্থনীতি']
ক্রিস্টোফিড

পছন্দ করুন ওপি না-আলফা অক্ষরগুলি কীভাবে আচরণ করা উচিত তা বলে না।
জন লা রুই

4
সত্য, তবে এই বর্তমান রেজেক্স পদ্ধতিতে dropsসমস্ত নিয়মিত (কেবল প্লেইন আলফা) শব্দ যা বড় হাতের অক্ষর দিয়ে শুরু হয় না। আমি সন্দেহ করি যে ওপির উদ্দেশ্য ছিল।
ক্রিস্টোফিড

9

@ ক্রিস্টোফিডের সমাধানে একটি প্রকরণ

s = 'TheLongAndWindingRoad'

pos = [i for i,e in enumerate(s+'A') if e.isupper()]
parts = [s[pos[j]:pos[j+1]] for j in xrange(len(pos)-1)]

print parts

4
দুর্দান্ত এক - এটি লাতিন-সহ অকার্যকর অক্ষরের সাথেও কাজ করে। এখানে দেখানো রেজেক্স সমাধানগুলি তা করে না।
অ্যালেক্সভিউআর

7

তাকাতে ব্যবহার করুন:

পাইথন ৩.7 এ আপনি এটি করতে পারেন:

re.split('(?=[A-Z])', 'theLongAndWindingRoad')

এবং এটি ফলন:

['the', 'Long', 'And', 'Winding', 'Road']

6
import re
filter(None, re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad"))

বা

[s for s in re.split("([A-Z][^A-Z]*)", "TheLongAndWindingRoad") if s]

4
ফিল্টারটি সম্পূর্ণ অপ্রয়োজনীয় এবং ক্যাপচার গ্রুপের সাথে সরাসরি রেগেক্স বিভক্ত করার জন্য আপনাকে কিছুই কিনে না: [s for s in re.compile(r"([A-Z][^A-Z]*)").split( "TheLongAndWindingRoad") if s]প্রদান['The', 'Long', 'And', 'Winding', 'Road']
স্মি

4
@ এসএমসি: এই ব্যবহারটি filterশর্তের সাথে তালিকার বোঝাপড়ার সমান। এর বিরুদ্ধে কিছু আছে কি?
গাব

4
আমি জানি এটি একটি শর্তের সাথে একটি তালিকা বোঝার সাথে প্রতিস্থাপন করা যেতে পারে, কারণ আমি সবেমাত্র এই কোডটি পোস্ট করেছি, তবে আপনি এটি অনুলিপি করেছেন। তালিকার বোধগম্যতা অধিকতর তিনটি কারণে এখানে রয়েছে: ক) সুস্পষ্ট প্রতিমা : তালিকার বোধগম্যতা পাইথোনিক আইডিয়ম এবং filter(lambdaconditionfunc, ...)খ এর চেয়ে বাম থেকে ডানদিকে পরিষ্কার পড়া ) পাইথন 3 -এ একটি পুনরাবৃত্তিকে filter()ফেরত দেয়। সুতরাং তারা সম্পূর্ণ সমতুল্য হবে না। গ) আমি আশা করি filter()খুব ধীরে
স্মি

5

আমি মনে করি যে এর চেয়ে আরও ভাল উত্তর হতে পারে স্ট্রিংটিকে এমন শব্দের মধ্যে বিভক্ত করা যা রাজধানীতে শেষ হয় না। এটি স্ট্রিংটি বড় হাতের অক্ষর দিয়ে শুরু না করে এমন ক্ষেত্রে পরিচালনা করবে।

 re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoad')

উদাহরণ:

>>> import re
>>> re.findall('.[^A-Z]*', 'aboutTheLongAndWindingRoadABC')
['about', 'The', 'Long', 'And', 'Winding', 'Road', 'A', 'B', 'C']

4
src = 'TheLongAndWindingRoad'
glue = ' '

result = ''.join(glue + x if x.isupper() else x for x in src).strip(glue).split(glue)

4
আপনি দয়া করে ব্যাখ্যা করতে পারেন কেন এটি সমস্যার ভাল সমাধান।
মাতাস ভাইটকেভিচিয়াস

আমি দুঃখিত. আমি শেষ পদক্ষেপটি ভুলে গেছি
user3726655

আমার কাছে সংক্ষিপ্ত, অজগর এবং স্ব-ব্যাখ্যামূলক বলে মনে হচ্ছে।

2

বিকল্প সমাধান (যদি আপনি সুস্পষ্ট রেজিক্সগুলি অপছন্দ করেন):

s = 'TheLongAndWindingRoad'

pos = [i for i,e in enumerate(s) if e.isupper()]

parts = []
for j in xrange(len(pos)):
    try:
        parts.append(s[pos[j]:pos[j+1]])
    except IndexError:
        parts.append(s[pos[j]:])

print parts

1

রেজেক্স ছাড়াই অন্য একটি এবং চাইলে স্বতন্ত্র বড় হাতের অক্ষরে রাখার ক্ষমতা

def split_on_uppercase(s, keep_contiguous=False):
    """

    Args:
        s (str): string
        keep_contiguous (bool): flag to indicate we want to 
                                keep contiguous uppercase chars together

    Returns:

    """

    string_length = len(s)
    is_lower_around = (lambda: s[i-1].islower() or 
                       string_length > (i + 1) and s[i + 1].islower())

    start = 0
    parts = []
    for i in range(1, string_length):
        if s[i].isupper() and (not keep_contiguous or is_lower_around()):
            parts.append(s[start: i])
            start = i
    parts.append(s[start:])

    return parts

>>> split_on_uppercase('theLongWindingRoad')
['the', 'Long', 'Winding', 'Road']
>>> split_on_uppercase('TheLongWindingRoad')
['The', 'Long', 'Winding', 'Road']
>>> split_on_uppercase('TheLongWINDINGRoadT', True)
['The', 'Long', 'WINDING', 'Road', 'T']
>>> split_on_uppercase('ABC')
['A', 'B', 'C']
>>> split_on_uppercase('ABCD', True)
['ABCD']
>>> split_on_uppercase('')
['']
>>> split_on_uppercase('hello world')
['hello world']

1

এই more_itertools.split_beforeসরঞ্জাম দিয়ে সম্ভব ।

import more_itertools as mit


iterable = "TheLongAndWindingRoad"
[ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())]
# ['The', 'Long', 'And', 'Winding', 'Road']

এটি একক ঘটনাগুলিও বিভক্ত হওয়া উচিত, অর্থাত্ 'ABC'আমি যা পেতে চাই তা থেকে ['A', 'B', 'C']

iterable = "ABC"
[ "".join(i) for i in mit.split_before(iterable, pred=lambda s: s.isupper())]
# ['A', 'B', 'C']

more_itertoolsএকটি তৃতীয় পক্ষের প্যাকেজ হ'ল 60+ দরকারী সরঞ্জাম সহ সমস্ত আসল তাত্ত্বিক রেসিপিগুলির জন্য বাস্তবায়ন , যা তাদের ম্যানুয়াল বাস্তবায়নকে বাধা দেয়।


1

পাইথোনিক উপায় হতে পারে:

"".join([(" "+i if i.isupper() else i) for i in 'TheLongAndWindingRoad']).strip().split()
['The', 'Long', 'And', 'Winding', 'Road']

পুনরায় / পুনরায় 2 এড়িয়ে ইউনিকোডের পক্ষে ভাল কাজ করে।

"".join([(" "+i if i.isupper() else i) for i in 'СуперМаркетыПродажаКлиент']).strip().split()
['Супер', 'Маркеты', 'Продажа', 'Клиент']

0

রেগেক্স বা গণনা না করে বিকল্প উপায়:

word = 'TheLongAndWindingRoad'
list = [x for x in word]

for char in list:
    if char != list[0] and char.isupper():
        list[list.index(char)] = ' ' + char

fin_list = ''.join(list).split(' ')

আমি মনে করি যে খুব বেশি পদ্ধতিতে শিকল ছাড়াই বা দীর্ঘ তালিকা বোধগম্যতা যা পড়া কঠিন read


0

একটি বিকল্প উপায় ব্যবহার enumerateএবংisupper()

কোড:

strs = 'TheLongAndWindingRoad'
ind =0
count =0
new_lst=[]
for index, val in enumerate(strs[1:],1):
    if val.isupper():
        new_lst.append(strs[ind:index])
        ind=index
if ind<len(strs):
    new_lst.append(strs[ind:])
print new_lst

আউটপুট:

['The', 'Long', 'And', 'Winding', 'Road']

0

পোস্টটি পড়লে কী মনে আসছিল তা ভাগ করে নেওয়া। অন্যান্য পোস্ট থেকে পৃথক।

strs = 'TheLongAndWindingRoad'

# grab index of uppercase letters in strs
start_idx = [i for i,j in enumerate(strs) if j.isupper()]

# create empty list
strs_list = []

# initiate counter
cnt = 1

for pos in start_idx:
    start_pos = pos

    # use counter to grab next positional element and overlook IndexeError
    try:
        end_pos = start_idx[cnt]
    except IndexError:
        continue

    # append to empty list
    strs_list.append(strs[start_pos:end_pos])

    cnt += 1

-1

প্রদত্ত প্রতিটি বড় হাতের অক্ষর 'এল' প্রতিস্থাপন করে খালি জায়গার সাথে সেই অক্ষর "এল" দিয়ে দিন। আমরা তালিকা বোধগম্যতা ব্যবহার করে এটি করতে পারি বা কোনও ক্রিয়াকলাপটিকে নিম্নলিখিত হিসাবে সংজ্ঞায়িত করতে পারি।

s = 'TheLongANDWindingRoad ABC A123B45'
''.join([char if (char.islower() or not char.isalpha()) else ' '+char for char in list(s)]).strip().split()
>>> ['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road', 'A', 'B', 'C', 'A123', 'B45']

আপনি যদি কোনও ফাংশনে যেতে চান, তবে এখানেই।

def splitAtUpperCase(text):
    result = ""
    for char in text:
        if char.isupper():
            result += " " + char
        else:
            result += char
    return result.split()

প্রদত্ত উদাহরণের ক্ষেত্রে:

print(splitAtUpperCase('TheLongAndWindingRoad')) 
>>>['The', 'Long', 'A', 'N', 'D', 'Winding', 'Road']

তবে বেশিরভাগ সময় যখন আমরা বড় হাতের অক্ষরে বাক্য বিভাজন করি তখন সাধারণত এটি ঘটে থাকে যে আমরা সংক্ষেপগুলি বজায় রাখতে চাই যা সাধারণত বড় হাতের অক্ষরের ধারাবাহিক ধারা থাকে। নীচের কোডটি সাহায্য করবে।

def splitAtUpperCase(s):
    for i in range(len(s)-1)[::-1]:
        if s[i].isupper() and s[i+1].islower():
            s = s[:i]+' '+s[i:]
        if s[i].isupper() and s[i-1].islower():
            s = s[:i]+' '+s[i:]
    return s.split()

splitAtUpperCase('TheLongANDWindingRoad')

>>> ['The', 'Long', 'AND', 'Winding', 'Road']

ধন্যবাদ


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