पायथन में एक चरित्र को एक स्ट्रिंग में बदलना


385

एक स्ट्रिंग में एक चरित्र को बदलने के लिए पायथन में सबसे आसान तरीका क्या है?

उदाहरण के लिए:

text = "abcdefg";
text[1] = "Z";
           ^

जवाबों:


534

तार को संशोधित न करें।

सूचियों के रूप में उनके साथ काम करें; जरूरत पड़ने पर ही उन्हें तार में घुमाएं।

>>> s = list("Hello zorld")
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'z', 'o', 'r', 'l', 'd']
>>> s[6] = 'W'
>>> s
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
>>> "".join(s)
'Hello World'

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


4
गति / दक्षता की तलाश करने वालों, इसे पढ़ें
अनीसहम्द 777

4
"तार को संशोधित न करें।" क्यों
21

2
"बनाएं-> संशोधित-> क्रमबद्ध करें-> असाइन करें-> मुफ़्त" s [6] = 'W' से अधिक प्रभावशाली? हम्म ... अन्य भाषाओं ने इसे "बहुत" कारणों के बावजूद अनुमति क्यों दी? दिलचस्प है कि कैसे एक अजीब डिजाइन का बचाव किया जा सकता है (प्यार के लिए मुझे लगता है)। पायथन कोर को एक फ़ंक्शन MID (strVar, index, newChar) जोड़ने का सुझाव क्यों नहीं दिया जाता है जो सीधे पूरे तार के साथ अनावश्यक रूप से बाइट फेरबदल के बजाय चार मेमोरी स्थिति तक पहुंचता है?
ऑस्कर

@hacksoi, @oscar, कारण काफी सरल है: जब कोई पासिंग-ऑन-मॉडिफिकेशन लागू करने के लिए पासिंग पॉइंटर्स को रिफ़काउंट करने की आवश्यकता नहीं है, या किसी स्ट्रिंग को संशोधित करना चाहता है तो मामले में पूरी स्ट्रिंग की प्रतिलिपि बनाएँ - इससे जेनेरिक में गति में वृद्धि होती है उपयोग। MIDस्लाइस के कारण जैसी चीजों की कोई आवश्यकता नहीं है :s[:index] + c + s[index+1:]
मल्टीस्किल

1
@oscar गूंगी भाषाओं से मेरा मतलब है कि वे यूनिकोड से नहीं निपटते हैं जब तक कि आप उन्हें स्पष्ट रूप से नहीं बताते हैं। बेशक आप सी में यूनिकोड सक्षम एप्लिकेशन लिख सकते हैं। लेकिन आपको हर समय इसकी देखभाल करनी होगी और परेशानी से बचने के लिए इसे स्पष्ट रूप से परखने की जरूरत है। सब कुछ मशीन-उन्मुख है। मैंने पायथन सीखने से पहले PHP के साथ काम किया, और वह भाषा कुल गड़बड़ है। तेजी से सीपीयू पर आपके नोट के बारे में मैं पूरी तरह से आपके साथ हूं। लेकिन उस समस्या का एक हिस्सा समय से पहले अनुकूलन का लोकप्रिय अस्वीकृति है, जो रास्ते में बहुत सारे सीपीयू चक्रों को लीक करके दुभाषियों और पुस्तकालयों को धीमा कर देता है।
बछसौ

202

सबसे तेज़ विधि?

इसके तीन तरीके हैं। गति चाहने वालों के लिए मैं 'विधि 2' सुझाता हूँ

विधि 1

इस उत्तर द्वारा दिया गया

text = 'abcdefg'
new = list(text)
new[6] = 'W'
''.join(new)

'मेथड 2' की तुलना में यह काफी धीमा है

timeit.timeit("text = 'abcdefg'; s = list(text); s[6] = 'W'; ''.join(s)", number=1000000)
1.0411581993103027

विधि 2 (फास्ट विधि)

इस उत्तर द्वारा दिया गया

text = 'abcdefg'
text = text[:1] + 'Z' + text[2:]

जो बहुत तेज है:

timeit.timeit("text = 'abcdefg'; text = text[:1] + 'Z' + text[2:]", number=1000000)
0.34651994705200195

विधि 3:

बाइट सरणी:

timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)
1.0387420654296875

1
यह देखने के लिए दिलचस्प होगा कि यह बाईट्रेयर पद्धति के खिलाफ भी कैसा है।
गाबोरस

1
अच्छा सुझाव। बाईट्रेयर विधि भी धीमी है: timeit.timeit("text = 'abcdefg'; s = bytearray(text); s[1] = 'Z'; str(s)", number=1000000)सबसे तेज दो बार।
मेहदी नेल्लन

2
परीक्षणों की सराहना करें, जो मुझे पुनर्विचार करते हैं कि मुझे पायथन स्ट्रिंग्स को कैसे हेरफेर करना चाहिए।
स्पेक्ट्रल

1
अच्छा लगा। कृपया विधि 3 को भी शामिल करने के लिए उत्तर को संपादित करें (बायट्रेयर)।
aneesAhmed777

1
यह ध्यान दिया जाना चाहिए कि यहां अधिकांश समय रूपांतरणों में बिताया जाता है ... (स्ट्रिंग -> बाइट सरणी)। यदि आपके पास स्ट्रिंग बनाने के लिए कई संपादन हैं, तो बाइट सरणी विधि अधिक तेज़ होगी।
इयान सुदबेरी


37

अजगर के तार अपरिवर्तनीय हैं, आप उन्हें कॉपी बनाकर बदलते हैं।
सबसे आसान तरीका है कि आप क्या चाहते हैं:

text = "Z" + text[1:]

text[1:]रिटर्न में स्ट्रिंग textसमाप्त करने के लिए स्थिति 1 से, पदों 0 से गिनती तो '1' दूसरा चरित्र है।

संपादित करें: आप स्ट्रिंग के किसी भी भाग के लिए उसी स्ट्रिंग स्लाइसिंग तकनीक का उपयोग कर सकते हैं

text = text[:1] + "Z" + text[2:]

या यदि पत्र केवल एक बार प्रकट होता है तो आप नीचे दी गई खोज और प्रतिस्थापित तकनीक का उपयोग कर सकते हैं


मैं द्वितीय चरित्र का उल्लेख करता हूं, IE। जगह नंबर 1 पर चरित्र (जैसा कि प्रथम चरित्र, नंबर 0 पर
अपील किया गया है

पाठ [0] + "Z" + पाठ [२:]
१g:

13

अजगर 2.6 और अजगर 3 के साथ शुरू करके आप बायट्रायर्स का उपयोग कर सकते हैं जो परस्पर हैं (तार के विपरीत तत्व-वार बदला जा सकता है):

s = "abcdefg"
b_s = bytearray(s)
b_s[1] = "Z"
s = str(b_s)
print s
aZcdefg

संपादित करें: बदलकर s करने के लिए

edit2: जैसा कि टू-बिट अल्केमिस्ट ने टिप्पणियों में उल्लेख किया है, यह कोड यूनिकोड के साथ काम नहीं करता है।


यह उत्तर गलत है। एक बात के लिए, यह होना चाहिए bytearray(s), नहीं bytearray(str)। दूसरे के लिए, यह उत्पादन करेगा TypeError: string argument without an encoding:। यदि आप एन्कोडिंग निर्दिष्ट करते हैं, तो आप प्राप्त करते हैं TypeError: an integer is required। यही पायथन 3 या पायथन 2 के यूनिकोड के साथ है। यदि आप पायथन 2 (एक सही दूसरी पंक्ति के साथ) में ऐसा करते हैं, तो यह गैर-एएससीआईआई पात्रों के लिए काम नहीं करेगा क्योंकि वे सिर्फ एक बाइट नहीं हो सकते हैं। इसके साथ प्रयास करें s = 'Héllo'और आपको मिलेगा 'He\xa9llo'
दो-बिट अल्केमिस्ट

मैंने पायथन 2.7.9 पर फिर से यह कोशिश की। मैं आपके द्वारा बताई गई त्रुटि को पुन: उत्पन्न नहीं कर सकता (टाइपर्रर: एन्कोडिंग के बिना स्ट्रिंग तर्क)।
महमूद

यदि आप यूनिकोड का उपयोग कर रहे हैं तो यह त्रुटि लागू होती है। कोशिश करो s = u'abcdefg'
दो-बिट अल्केमिस्ट

4
यह मत करो। यह विधि स्ट्रिंग एन्कोडिंग की पूरी अवधारणा को अनदेखा करती है, जिसका अर्थ है कि यह केवल ASCII वर्णों पर काम करने के लिए होता है। इस दिन और उम्र में आप ASCII नहीं मान सकते, भले ही आप अंग्रेजी बोलने वाले देश में एक अंग्रेजी वक्ता हों। Python3 की सबसे बड़ी पिछड़ी असंगतता, और मेरी राय में सबसे महत्वपूर्ण, यह पूरी बाइट = स्ट्रिंग झूठी समकक्षता को ठीक कर रही है। इसे वापस मत लाओ।
एडम

5

जैसा कि अन्य लोगों ने कहा है, आमतौर पर पायथन तार अपरिवर्तनीय माना जाता है।

हालाँकि, यदि आप CPython, python.org पर कार्यान्वयन का उपयोग कर रहे हैं, तो मेमोरी में स्ट्रिंग संरचना को संशोधित करने के लिए ctypes का उपयोग करना संभव है।

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

अजगर में संवेदनशील के रूप में मार्क डेटा

मैं इसे संपूर्णता के लिए उल्लेख करता हूं, और यह आपका अंतिम उपाय होना चाहिए क्योंकि यह हैकिश है।


6
अखिरी सहारा? यदि आप कभी ऐसा करते हैं तो आप अचानक बुराई के रूप में ब्रांडेड हो जाते हैं!
क्रिस मॉर्गन

@ChrisMorgan यदि आपके स्ट्रिंग में पासवर्ड है, तो इसे s = '' से साफ़ करना पर्याप्त नहीं है क्योंकि पासवर्ड अभी भी स्मृति में कहीं लिखा हुआ है। Ctypes के माध्यम से इसे साफ़ करना ही एकमात्र रास्ता है।
काबु

1
@Cabu मैं होता कभी नहीं के तहत किसी भी परिस्थिति कोड है कि ऐसा ही किया स्वीकार करते हैं। यदि आपका डेटा संवेदनशील है और आप इस तरह की सुरक्षा की परवाह करते हैं, strतो यह आपके लिए सही प्रकार नहीं है। बस इसका उपयोग न करें। bytearrayइसके बजाय कुछ का उपयोग करें । (बेहतर अभी भी, इसे किसी ऐसी चीज़ में लपेटें जिससे आप इसे अपारदर्शी डेटा के रूप में अधिक या कम मान सकते हैं ताकि आप वास्तव में प्रभावित होंstr , ताकि आप दुर्घटनाओं से बचाने के लिए इसे से पुनः प्राप्त न कर सकें । इसके लिए एक पुस्तकालय हो सकता है। कोई विचार नहीं है।)
क्रिस मॉर्गन

4

यह कोड मेरा नहीं है। मुझे वह साइट फ़ॉर्म याद नहीं आ रहा है, जहाँ मैंने उसे लिया था। दिलचस्प बात यह है कि आप इसका उपयोग एक चरित्र या एक से अधिक चौराहों को बदलने के लिए कर सकते हैं। हालांकि यह उत्तर बहुत देर से आया है, मेरे जैसे नौसिखिए (कभी भी) इसे उपयोगी पा सकते हैं।

पाठ फ़ंक्शन बदलें।

mytext = 'Hello Zorld'
mytext = mytext.replace('Z', 'W')
print mytext,

11
इस सवाल का जवाब नहीं है। यह वह नहीं है जो सभी में वांछित था।
क्रिस मॉर्गन

2
यदि आप केवल पहले को बदलना चाहते हैं तो यह कोड खराब है lmytext = mytext.replace('l', 'W')->HeWWo Zorld
ओकर

यदि आप शल्यचिकित्सा केवल 1 वर्ण (जो मैं कर रहा हूं) की जगह लेना चाहता हूं, तो यह बिल पूरी तरह से फिट बैठता है। धन्यवाद!
ProfVersaggi

@ProfVersaggi यह बिल्कुल गलत है। ऊपर Ooker की टिप्पणी देखें।
दो-बिट अल्केमिस्ट

3
@ जोकर यदि आप केवल पहले चरित्र को बदलना चाहते हैं, जिसका आप उपयोग कर सकते हैं mytext = mytext.replace('l', 'W',1)डॉक्टर से लिंक
एलेक्स

2

दरअसल, स्ट्रिंग्स के साथ, आप ऐसा कुछ कर सकते हैं:

oldStr = 'Hello World!'    
newStr = ''

for i in oldStr:  
    if 'a' < i < 'z':    
        newStr += chr(ord(i)-32)     
    else:      
        newStr += i
print(newStr)

'HELLO WORLD!'

असल में, मैं एक नए तार में एक साथ "+" तार जोड़ रहा हूं :)।


4
यह बहुत धीमी गति से होने वाला है क्योंकि प्रत्येक संघात को एक नई स्ट्रिंग ऑब्जेक्ट का उत्पादन करना पड़ता है, क्योंकि वे अपरिवर्तनीय हैं, जो कि यह प्रश्न है।
टू-बिट अल्केमिस्ट

0

यदि आपकी दुनिया 100% है ascii/utf-8(उपयोग के बहुत सारे मामले उस बॉक्स में फिट हैं):

b = bytearray(s, 'utf-8')
# process - e.g., lowercasing: 
#    b[0] = b[i+1] - 32
s = str(b, 'utf-8')

अजगर 3.7.3


0

मैं एक स्ट्रिंग में एक चरित्र को बदलने का एक और तरीका जोड़ना चाहूंगा।

>>> text = '~~~~~~~~~~~'
>>> text = text[:1] + (text[1:].replace(text[0], '+', 1))
'~+~~~~~~~~~'

स्ट्रिंग को सूची में बदलने और ith मान को बदलने के बाद फिर से जुड़ने की तुलना में यह कितना तेज है।

सूची दृष्टिकोण

>>> timeit.timeit("text = '~~~~~~~~~~~'; s = list(text); s[1] = '+'; ''.join(s)", number=1000000)
0.8268570480013295

मेरा समाधान

>>> timeit.timeit("text = '~~~~~~~~~~~'; text=text[:1] + (text[1:].replace(text[0], '+', 1))", number=1000000)
0.588400217000526
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.