2009-04-16 7 views
73

मैं रुबी में दी गई लंबाई के सबस्ट्रिंग्स में एक स्ट्रिंग को जोड़ने के लिए एक सुरुचिपूर्ण और कुशल तरीका ढूंढ रहा हूं।रुबी में दी गई लंबाई के टुकड़ों में स्ट्रिंग को काटने का सबसे अच्छा तरीका क्या है?

def chunk(string, size) 
    (0..(string.length-1)/size).map{|i|string[i*size,size]} 
end 

>> chunk("abcdef",3) 
=> ["abc", "def"] 
>> chunk("abcde",3) 
=> ["abc", "de"] 
>> chunk("abc",3) 
=> ["abc"] 
>> chunk("ab",3) 
=> ["ab"] 
>> chunk("",3) 
=> [] 

आप chunk("", n) चाहते हो सकता है [""] बजाय [] वापस जाने के लिए:

अब तक सबसे अच्छा मैं के साथ आ सकता है यह है। यदि ऐसा है, तो बस इसे विधि की पहली पंक्ति के रूप में जोड़ें:

return [""] if string.empty? 

क्या आप किसी बेहतर समाधान की अनुशंसा करेंगे? इस सुरुचिपूर्ण और कुशल समाधान के लिए जेरेमी Ruten को

संपादित

धन्यवाद:

def chunk(string, size) 
    string.scan(/.{1,#{size}}/) 
end 

उत्तर

132

उपयोग String#scan:

"abcdefghijklmnopqrstuvwxyz".chars.to_a.each_slice(3).to_a.map {|s| s.to_s } 

=> [ "abc", "def", "GHI", "JKL", "MNO:

>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{4}/) 
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx"] 
>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{1,4}/) 
=> ["abcd", "efgh", "ijkl", "mnop", "qrst", "uvwx", "yz"] 
>> 'abcdefghijklmnopqrstuvwxyz'.scan(/.{1,3}/) 
=> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"] 
+0

ठीक है, अब यह उत्कृष्ट है! मुझे पता था कि एक बेहतर तरीका होना चाहिए था। बहुत धन्यवाद जेरेमी रूटेन। – MiniQuark

+1

डीफ़ खंड (स्ट्रिंग, आकार); string.scan (/ {1, # {आकार}} /।); अंत – MiniQuark

+1

वाह, अब मुझे बेवकूफ लगता है। स्कैन कैसे काम करता है यह जांचने के लिए मैंने कभी भी परेशान नहीं किया है। – Chuck

0

कुछ अन्य बाधाओं आपके मन में है क्या? अन्यथा मैं बहुत तरह

[0..10].each { 
    str[(i*w),w] 
} 
+0

के लिए मैं वास्तव में अलग कुछ सरल, सुरुचिपूर्ण और कुशल होने से, किसी भी बाधा नहीं है। मुझे आपका विचार पसंद है, लेकिन क्या आप इसे एक विधि में अनुवाद करना चाहते हैं? [0..10] शायद थोड़ा और जटिल हो जाएगा। – MiniQuark

+0

मैंने स्ट्र [i * w ... (i + 1) * w] के बजाय str [i * w, w] का उपयोग करने के लिए अपना उदाहरण तय किया। टीएक्स – MiniQuark

+0

यह होना चाहिए (1.10)। [0..10] .each के बजाय चयन करें। [1..10] एक सरणी है जिसमें एक तत्व होता है - एक सीमा। (1..10) खुद ही सीमा है। और + प्रत्येक + मूल संग्रह देता है जिसे इसे ब्लॉक द्वारा लौटाए गए मानों के बजाय ([1..10] इस मामले में) कहा जाता है। हम + मानचित्र + यहां चाहते हैं। – Chuck

1
test.split(/(...)/).reject {|v| v.empty?} 

अस्वीकारेंनीचे आवश्यक है, क्योंकि यह अन्यथा सेट के बीच खाली स्थान शामिल है कुछ सरल करने के लिए परीक्षा होगी। मेरा regex-fu यह देखने के लिए काफी नहीं है कि मेरे सिर के ऊपर से ठीक से कैसे ठीक किया जाए।

+0

स्कैन एप्रोच गैर मिलान वाले कैरेक्टरों के बारे में भूल जाएगा, यानी: यदि आप 3 भागों पर 10 लंबाई स्ट्रिंग स्लाइस के साथ प्रयास करते हैं, तो आपके पास 3 भाग होंगे और 1 तत्व गिरा दिया जाएगा, आपका अपमान ऐसा नहीं करता है, इसलिए यह सबसे अच्छा है। –

15

यहाँ एक और तरीका यह करने के लिए है "" PQR "," स्टू "," vwx "," YZ "]

+11

वैकल्पिक रूप से: '" abcdefghijklmnopqrstuvwxyz ".chars.each_slice (3) .map (&: join)' – Finbarr

+3

मुझे यह पसंद है क्योंकि यह स्ट्रिंग पर काम करता है जिसमें न्यूलाइन होती है। –

+1

यह स्वीकार्य समाधान होना चाहिए। यदि लंबाई _pattern_ से मेल नहीं खाती है तो स्कैन का उपयोग करके अंतिम टोकन ड्रॉप हो सकता है। – count0

2

मुझे लगता है कि यह सबसे कारगर उपाय है यदि आप जानते हैं आपके स्ट्रिंग हिस्सा आकार की एक बहु है

def chunk(string, size) 
    (string.length/size).times.collect { |i| string[i * size, size] } 
end 

और भागों

def parts(string, count) 
    size = string.length/count 
    count.times.collect { |i| string[i * size, size] } 
end 
+1

यदि आप 'string.length/size' को '(string.length + size - 1)/size' के साथ प्रतिस्थापित करते हैं तो आपकी स्ट्रिंग को खंड आकार का एक बहु होना आवश्यक नहीं है - यह पैटर्न सी कोड में सामान्य है पूर्णांक छंटनी के साथ सौदा। – nitrogen

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

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