2011-05-16 9 views
8

How do I limit the number of replacements when using gsub? में, किसी ने सीमित संख्या में प्रतिस्थापन करने का निम्न तरीका सुझाया:ब्लॉक को कितनी बार बुलाया जाता है, मैं कैसे सीमित करूं?

str = 'aaaaaaaaaa' 
count = 5 
p str.gsub(/a/){if count.zero? then $& else count -= 1; 'x' end} 
# => "xxxxxaaaaa" 

यह काम करता है, लेकिन कोड प्रतिस्थापन (5) को प्रतिस्थापित करने के लिए कितनी बार प्रतिस्थापन (5) "अगर कोई प्रतिस्थापन होना चाहिए, तो $& अन्यथा)। क्या दोनों को अलग करना संभव है?

(यदि इस परिदृश्य में दो चीजों को अलग करना बहुत मुश्किल है, लेकिन यह किसी अन्य परिदृश्य में किया जा सकता है, इसे उत्तर के रूप में पोस्ट करें)

+0

मुझे लगता है कि में दिलचस्पी थी। मैंने 'MatchData # start',' MatchData # length', 'MatchData # end', 'स्ट्रिंग # मिलान (regex, position)', या किसी भी तरह' gsub' के साथ '/ \ G /' का उपयोग करने का उपयोग करने के बारे में सोचा था, लेकिन पूरी तरह से काम नहीं किया। शायद कोई इस लाइन के साथ, या एक पूरी तरह से अलग परिप्रेक्ष्य के साथ एक विचार विस्तृत कर सकते हैं। उत्तर के लिए आगे देख रहे हैं। – sawa

उत्तर

8

कैसे सिर्फ एक तर्क के रूप प्रतिस्थापन निकालने और encapsulating के बारे में एक विधि के अंदर ब्लॉक बंद करके काउंटर?

str = "aaaaaaaaaaaaaaa" 

def replacements(replacement, limit) 
    count = limit 
    lambda { |original| if count.zero? then original else count -= 1; replacement end } 
end 

p str.gsub(/a/, &replacements("x", 5)) 

आप इसे और भी अधिक सामान्य प्रतिस्थापन के लिए एक ब्लॉक का उपयोग करके कर सकते हैं:

def limit(n, &block) 
    count = n 
    lambda do |original| 
     if count.zero? then original else count -= 1; block.call(original) end 
    end 
end 

सामान अब आप कर सकते हैं

तरह
p str.gsub(/a/, &limit(5) { "x" }) 
p str.gsub(/a/, &limit(5, &:upcase)) 
+0

अच्छा। हो सकता है कि आप एक कदम आगे जा सकें और 'gsub_with_limit (regex, limit, वैकल्पिक_replacement, और वैकल्पिक_block_replacement) '? मुझे यकीन नहीं है। – sawa

+0

@sawa: निश्चित रूप से, लेकिन ध्यान दें कि इसका उपयोग 'gsub' से अन्य विधियों के साथ किया जा सकता है। उदाहरण के लिए, '[* 1..10]। मैप (और सीमा (5) {| x | 2 * x})'। – hammar

+0

मुझे इसका एहसास नहीं हुआ। यह अच्छा है। लेकिन किसी भी तरह, वाक्यविन्यास थोड़ा अजीब है। – sawa

2

gsub जितनी बार वास्तव में ब्लॉक कॉल करेंगे चूंकि रेगेक्स स्ट्रिंग से मेल खाता है। इसे रोकने का एकमात्र तरीका ब्लॉक में break पर कॉल करना है, हालांकि यह एक सार्थक वापसी मूल्य उत्पन्न करने से gsub भी रखेगा।

तो नहीं, जब तक कि आप ब्लॉक में ब्रेक को कॉल न करें (जो उपज करने वाली विधि में किसी और कोड को रोकने से रोकता है और इस प्रकार विधि को कुछ भी लौटने से रोकता है), एक विधि को ब्लॉक करने की विधि को पूरी तरह से निर्धारित किया जाता है विधि स्वयं तो यदि आप gsub चाहते हैं तो केवल 5 गुना पैदा करें, ऐसा करने का एकमात्र तरीका रेगेक्स में गुजरना है जो केवल दिए गए तारों से पांच बार मेल खाता है।

+0

यदि आप 'gsub!' का उपयोग 'ब्रेक' के साथ करते हैं, तो यह वही होगा? – sawa

+2

@sawa: यदि आप 'gsub!' ब्लॉक में ब्रेक कहते हैं, तो स्ट्रिंग अपरिवर्तित रहेगी (कम से कम एमआरआई 1.9.2 में)। संभवतः 'gsub!' पहले एक अस्थायी स्ट्रिंग बनाता है और फिर अंत में 'प्रतिस्थापन' को कॉल करता है (जो ब्रेक कहलाता है तो कभी नहीं होगा)। – sepp2k

1

आप gsub() का उपयोग क्यों कर रहे हैं? इसके डिजाइन द्वारा, gsub किसी चीज की सभी घटनाओं को प्रतिस्थापित करने के लिए डिज़ाइन किया गया है, इसलिए, जिस बल्ले से आप लड़ रहे हैं उसे ठीक करें। बजाय

उपयोग sub:

str = 'aaaaaaaaaa' 
count = 5 
count.times { str.sub!(/a/, 'x') } 
p str 
# >> "xxxxxaaaaa" 

str = 'mississippi' 
2.times { str.sub!(/s/, '5') } 
2.times { str.sub!(/s/, 'S') } 
2.times { str.sub!(/i/, '1') } 
p str 
# >> "m1551SSippi" 
+2

यह वास्तव में मूल प्रश्न में प्रस्तुत एंड्रयू समाधान था। लेकिन जब यह प्रतिस्थापन स्ट्रिंग मिलान पैटर्न से मेल खाता है तो यह काम नहीं करता है; उदाहरण के लिए 'सब! (/ ए /, 'बिल्ली')'। – sawa

संबंधित मुद्दे