2011-03-09 14 views
6

में एक स्ट्रिंग में एक वर्ण को संशोधित करना लुआ में एक स्ट्रिंग में स्थिति एन पर किसी चरित्र को प्रतिस्थापित करने का कोई तरीका है।लुआ

यह वही है मैं अब तक के साथ आ गया है:

function replace_char(pos, str, r) 
    return str:sub(pos, pos - 1) .. r .. str:sub(pos + 1, str:len()) 
end 

str = replace_char(2, "aaaaaa", "X") 
print(str) 

मैं gsub उपयोग नहीं कर सकते या तो के रूप में उस स्थिति एन पर हर कब्जा, न सिर्फ कब्जा जगह लेंगे

उत्तर

12

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

अपने कोड पर यह बदलाव:

function replace_char(pos, str, r) 
    return str:sub(1, pos-1) .. r .. str:sub(pos+1) 
end 

लुआ सीधा करने का सबसे सीधा अनुवाद है। यह संभवतः अधिकांश उद्देश्यों के लिए पर्याप्त तेज़ है। मैंने बग तय कर दिया है कि उपसर्ग पहले pos-1 वर्णों का होना चाहिए, और इस तथ्य का लाभ उठाया कि यदि string.sub पर अंतिम तर्क गुम है तो यह -1 माना जाता है जो स्ट्रिंग के अंत के बराबर है।

लेकिन ध्यान दें कि यह कई अस्थायी स्ट्रिंग बनाता है जो स्ट्रिंग स्टोर में चारों ओर लटकाएंगे जब तक कि कचरा संग्रह उन्हें खाए। उपसर्ग और पोस्टफिक्स के लिए अस्थायी किसी भी समाधान से बचा नहीं जा सकता है। लेकिन इसे दूसरे द्वारा उपभोग करने वाले पहले .. ऑपरेटर के लिए अस्थायी बनाना होगा।

यह संभव है कि दो वैकल्पिक दृष्टिकोणों में से एक तेज़ी से हो सके। पहले solution offered by Paŭlo Ebermann है, लेकिन एक छोटी सी ट्वीक साथ:

function replace_char2(pos, str, r) 
    return ("%s%s%s"):format(str:sub(1,pos-1), r, str:sub(pos+1)) 
end 

यह string.format का उपयोग करता है उम्मीद है कि यह अतिरिक्त अस्थायी वस्तुओं की जरूरत के बिना अंतिम बफर आकार अनुमान लगा सकते हैं में परिणाम की विधानसभा करते हैं।

लेकिन सावधान रहना है कि string.format किसी भी स्ट्रिंग में किसी भी \0 पात्रों के साथ मुद्दों है की संभावना है कि वह अपने %s प्रारूप से होकर गुजरता है। विशेष रूप से, चूंकि इसे मानक सी के sprintf() फ़ंक्शन के संदर्भ में लागू किया गया है, इसलिए यह अपेक्षा करना उचित होगा कि इसे \0 की पहली घटना में प्रतिस्थापित स्ट्रिंग को समाप्त कर दिया जाए। (एक टिप्पणी में उपयोगकर्ता Delusional Logic द्वारा नोट किया गया।)

एक तीसरा विकल्प है कि मन में आता है यह है:

function replace_char3(pos, str, r) 
    return table.concat{str:sub(1,pos-1), r, str:sub(pos+1)} 
end 

table.concat कुशलता से एक अंतिम परिणाम में स्ट्रिंग की एक सूची कोनकैटेनेट्स किया गया। इसमें एक वैकल्पिक दूसरा तर्क है जो तारों के बीच सम्मिलित करने के लिए पाठ है, जो "" पर डिफ़ॉल्ट है जो हमारे उद्देश्य के अनुरूप है।

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

+1

गहराई से स्पष्टीकरण के लिए धन्यवाद – dotminic

+1

यह पुराना है। लेकिन मैंने अभी लिखा कुछ कोड में मामूली बग को हल कर लिया है। यह पता चला है कि '' replace_char2'' विधि शून्य ('' \ 0'') वर्णों को सम्मिलित नहीं करती है। –

+0

@DelusionalLogic अच्छा बिंदु। 'string.format' मानक सी के 'sprintf()' फ़ंक्शन पर दृढ़ता से आधारित है, और इसमें एम्बेडेड एनयूएल बाइट्स के साथ समस्याएं होने की संभावना है। – RBerteig

5

आप शाब्दिक 1 और 3 की बजाय अपने फ़ंक्शन के अंदर pos का उपयोग करना चाहिए, लेकिन इसके अलावा यह अच्छा दिखता है। चूंकि लुआ तार अचूक हैं क्योंकि आप वास्तव में इससे बेहतर नहीं कर सकते हैं।

शायद

"%s%s%s":format(str:sub(1,pos-1), r, str:sub(pos+1, str:len()) 

.. ऑपरेटर से अधिक कुशल है, लेकिन मैं इसे शक - अगर यह पता चला है, एक टोंटी हो यह उपाय (और फिर सी में इस प्रतिस्थापन समारोह लागू करने का निर्णय) करने के लिए।

+1

हां '..' ऑपरेटर तारों को संयोजित करने का सबसे धीमा तरीका है क्योंकि प्रत्येक '..' के लिए एक नई स्ट्रिंग बनाई गई है। तेज़ तरीकों में 'string.format' और' table.concat' शामिल हैं। इससे किसी भी ध्यान देने योग्य प्रभाव नहीं हो सकते हैं, भले ही आप बहुत बड़े तारों या कई कॉन्सटेनेशन ऑपरेशंस के साथ काम नहीं कर रहे हों। उदाहरण के लिए, आउटपुट के रूप में इनपुट को सॉर्ट करने और पुनर्निर्माण करते समय इनपुट की प्रति पंक्ति लगभग 5 '..' का उपयोग कर 1 एमबी फ़ाइल से कम प्रोसेस करने के लिए 500 एमबी से अधिक मेमोरी का उपयोग करने के लिए मेरी एक स्क्रिप्ट थी। एक टेबल में तारों को स्टोर करने के लिए इसे बदलना और अंत में 'table.concat' ने इसे इतना तेज़ बना दिया कि मैंने मापने को भी परेशान नहीं किया। – Arrowmaster

+1

@Arrowmaster: क्या आप जानते हैं कि 'ए .. बी .. सी' में दो (केवल एक के बजाय) नए स्ट्रिंग बनाए गए हैं, या क्या आप इसे बस मानते हैं? सैद्धांतिक रूप से इसे केवल एक नई स्ट्रिंग बनाने के लिए कंपाइलर/दुभाषिया द्वारा अनुकूलित किया जा सकता है, जैसे यह जावा में '+' ऑपरेटर के लिए किया जाता है। आपका उदाहरण एक और मामला है, क्योंकि वहां आपको वास्तव में प्रत्येक कथन के साथ नए तार बनाना होगा। –

+0

@ पालो एबरमान हाँ मैंने अभी कोड कॉपी किया है, शब्दकोष को हटाने के लिए भूल गए हैं। @Arrowmaster @ Palolo Ebermann मैं .. ऑपरेटर की प्रारूप विधि से तुलना करूंगा। अंतर्दृष्टि के लिए धन्यवाद। – dotminic