2012-02-29 10 views
28

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

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

"This is a very long string that has more characters than I want in it." 

इस हो जाता है:

"This is a very long string that..." 

मैं इस के साथ शुरू कर रहा हूँ लेकिन स्पष्ट रूप से इस खाली स्थान के पर स्ट्रिंग समाप्त होने की समस्या से निपटने नहीं है।

<%= item.description[0..30] %>&hellip; 

उत्तर

36
s[0..30].gsub(/\s\w+\s*$/, '...') 

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

>> desc="This is some text it is really long" 

>> desc[0..30].gsub(/\s\w+$/,'...') 
"This is some text it is really " 

>> desc[0..30].gsub(/\s\w+\s*$/,'...') 
"This is some text it is..." 
+0

शुद्ध रूबी उत्तर के लिए धन्यवाद! पूरी तरह से काम किया। –

+2

यह ज्यादातर लोग नहीं चाहते हैं। यह इलिप्सिस को इस बात पर ध्यान दिए बिना कि स्ट्रिंग वास्तव में 30 वर्णों से अधिक है या नहीं। – gamut

+0

यह उत्तर किसी भी कारण से अंतिम शब्द को फेंक देता है, यहां तक ​​कि इसकी आवश्यकता नहीं है। स्ट्रिंग नहीं होनी चाहिए "यह कुछ पाठ है जो वास्तव में है ..." अधिक अपेक्षित परिणाम हो? – gorn

34

आप रेल उपयोग कर रहे हैं 4 तुम सिर्फ का उपयोग करना चाहिए निर्मित truncate सहायक विधि, उदा .:

<%= truncate item.description, length: 30, separator: /\w+/ %> 

स्ट्रिंग "..." छोटा कर दिया पाठ से जोड़ दिए जाएंगे; एक अलग स्ट्रिंग निर्दिष्ट करने के लिए, :omission विकल्प का उपयोग करें, उदा। omission: "xxx"

रेल के लिए 3.x :separator विकल्प एक स्ट्रिंग होना चाहिए। कई मामलों में :separator => " " देना ठीक होगा, लेकिन केवल रिक्त स्थान पकड़ता है और अन्य सफेद जगह नहीं। एक समझौता String#squish का उपयोग करना होगा, जो एक स्थान के साथ व्हाइटस्पेस के सभी अनुक्रमों को प्रतिस्थापित करता है (और अग्रणी और पीछे की ओर सफेद स्थान), उदाहरण के लिए "foo\n\tbar ".squish उपज "foo bar"। यह इस तरह दिखेगा:

<%= truncate item.description.squish, :length => 30, :separator => /\w/, 
             :omission => "&hellip;" %> 
+0

मैं रेल का उपयोग कर रहा हूं। धन्यवाद, वह दांव चल गया। –

+0

मुझे नहीं लगता कि आप विभाजक तर्क – fearofawhackplanet

+0

में रेगेक्स का उपयोग कर सकते हैं मैं रेल 3.2.13 का उपयोग कर रहा हूं और रेगेक्सपी विभाजक के लिए नहीं माना जाता है। NoMethodError: अपरिभाषित विधि 'mb_chars' के लिए/\ w /: Regexp – roychri

7

@ evfwcqcg का जवाब बहुत अच्छा है। मैंने पाया कि

  1. स्ट्रिंग में अन्य वर्ण शामिल हैं जो गैर-स्थान अल्फान्यूमेरिकल नहीं हैं।
  2. स्ट्रिंग वांछित लंबाई से कम है।

प्रदर्शन:

>> s = "How about we put some ruby method Class#Method in our string" 
=> "How about we put some ruby method Class#Method in our string" 
>> s[0..41].gsub(/\s\w+\s*$/, '...') 
=> "How about we put some ruby method Class#Me" 
>> s[0..999].gsub(/\s\w+\s*$/, '...') 
=> "How about we put some ruby method Class#Method in our..." 

यह मैं क्या उम्मीद नहीं है। अपेक्षा के अनुरूप

>> s = "This is some text it is really long" 
=> "This is some text it is really long" 
>> truncate s 
=> "This is some text it is..." 

फिर भी व्यवहार करते हैं: उत्पादन होता है,

def truncate s, length = 30, ellipsis = '...' 
    if s.length > length 
    s.to_s[0..length].gsub(/[^\w]\w+\s*$/, ellipsis) 
    else 
    s 
    end 
end 

परीक्षण कर जब यहाँ:

यहाँ क्या मैं इसे ठीक करने के लिए उपयोग कर रहा हूँ है।

>> s = "How about we put some ruby method Class#Method in our string" 
=> "How about we put some ruby method Class#Method in our string" 
>> truncate s, 41 
=> "How about we put some ruby method Class..." 
>> truncate s, 999 
=> "How about we put some ruby method Class#Method in our string" 

यह अधिक पसंद है।

+0

हालांकि यह @ evfwcqcg के उत्तर से बेहतर है, फिर भी मुझे नहीं पता कि आप आखिरी शब्द क्यों लेना चाहते हैं भले ही यह सीमा तक फिट हो। आपके अपमान के मामले में - आप टेक्स्ट को क्यों देखते हैं "यह कुछ पाठ है" वांछित परिणाम के रूप में "यह कुछ पाठ है, वास्तव में" में 30 वर्ण हैं और यह व्हाइटस्पेस पर भी समाप्त होता है। – gorn

+0

@gorn क्योंकि एक बार जब आप इलिप्सिस जोड़ते हैं, तो यह 30 से अधिक वर्ण होने जा रहा है। अनुमोदित, अगर एलिप्सिस की लंबाई आखिरी शब्द की लंबाई से अधिक है, तो यह 30 से अधिक वर्णों के लिए होगा। लेकिन ज्यादातर मामलों में, इलिप्सिस "..." होने के साथ, यह केवल 30 से अधिक हो जाएगा यदि अंतिम शब्द 1 वर्ण है, जो मुझे लगता है कि अक्सर ऐसा नहीं होता है। क्या आपको यह बेहतर बनाने के लिए कोई सुझाव है? – roychri

+0

मैं समझता हूं कि यह "ज्यादातर मामलों में काम करेगा", इसलिए मेरे रेंटिंग में व्यावहारिक मूल्य की तुलना में अधिक अकादमिक है, लेकिन जब मैं "गलत" कोड देखता हूं तो वही तरीका है। उसके लिए माफ़ करना। मैंने एक अलग जवाब के रूप में एक समाधान पोस्ट किया है, क्योंकि यह एक टिप्पणी के लिए बहुत लंबा हो गया है। वहां अपने विचार जोड़ने के लिए स्वतंत्र महसूस करें। – gorn

0
class String 
    def trunca(length=100, ellipsis='...') 
    self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip 
    end 
end 

उदाहरण:

-bash> irb 
2.0.0p247 :001 > class String 
2.0.0p247 :002?>  def trunca(length=100, ellipsis='...') 
2.0.0p247 :003?>   self.length > length ? self[0..length].gsub(/\s*\S*\z/, '').rstrip+ellipsis : self.rstrip 
2.0.0p247 :004?>  end 
2.0.0p247 :005?> end 
=> nil 
2.0.0p247 :006 > s = "This is a very long string that has more characters than I want to display." 
=> "This is a very long string that has more characters than I want to display." 
2.0.0p247 :007 > s.trunca(20) 
=> "This is a very long..." 
2.0.0p247 :008 > s.trunca(31) 
=> "This is a very long string that..." 
+1

इलिप्सिस की लंबाई के बारे में क्या? '123 456'.trunca (4)। लम्बाई => 6, 4 नहीं ... –

+0

मुझे लगता है कि पहली rstrip necesarry नहीं है। – gorn

1
desc.gsub(/([\w\s]{30}).+/,'\1...') 

@evfwcqcg द्वारा जवाब पर विस्तार, यह एक शुद्ध regex कि खाली स्थान के अनुगामी की समस्या का हल है।

irb(main):031:0> desc="This is some text it is really long" 
irb(main):033:0> desc.gsub(/([\w\s]{30}).+/,'\1...') 
=> "This is some text it is really..." 
irb(main):034:0> desc="This is some text it is really" 
=> "This is some text it is really" 
irb(main):035:0> desc.gsub(/([\w\s]{30}).+/,'\1...') 
=> "This is some text it is really" 
irb(main):036:0> desc="This is some text it is real" 
=> "This is some text it is real" 
irb(main):037:0> desc.gsub(/([\w\s]{30}).+/,'\1...') 
=> "This is some text it is real" 
+0

यह सादा गलत समाधान है। यदि आप मूल स्ट्रिंग के साथ प्रयास करते हैं "यह एक बहुत लंबी स्ट्रिंग है जिसमें इसके अलावा अधिक वर्ण हैं।" आप से "यह एक बहुत लंबी स्ट्रिंग था ..." ... – gorn

0

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

स्पष्ट रूप से यह निर्धारित करता है कि यह पहले लक्ष्य क्या है। हम स्ट्रिंग s को 30 वर्णों में छंटनी करना चाहते हैं और आखिरी शब्द को भी कटौती करना चाहते हैं, अगर यह पूरी तरह से फिट नहीं हो सकता है। हम परिणाम से पिछली जगहों को छीनना चाहते हैं और टेक्स्ट को छोटा होने पर, इलिप्सिस जोड़ना चाहते हैं।

पाठ अब तो सीमित कर रहा है, तो छोटा है की तुलना में आसान

s[0,s.rindex(/\s/,30)].rstrip + '...' 

अगर हम 30 वर्ण अधिकतम हो सकता है, की तुलना में यह से अंडाकार की लंबाई घटाकर के रूप में सरल है पूरे परिणाम चाहता था के रूप में 30. तो क्योंकि हम तीन बिंदु (और नहीं एक तीन-बिंदु चरित्र) की तुलना में हम

s[0,s.rindex(/\s/,27)].rstrip + '...' 

जरूरत है और अंतिम परिणाम (परीक्षण है कि क्या हम सब पर काट-छांट करने की आवश्यकता के साथ) का उपयोग करें:

if s.length<=30 
    s 
else 
    s[0,s.rindex(/\s/,27)].rstrip + '...' 
end 

यह बात करता है।


नोट: कुछ छायादार मामलों, कर रहे हैं जब वांछित परिणाम स्पष्ट नहीं है। यहाँ वे हैं:

  • स्ट्रिंग रिक्त स्थान (s= "Helo word ") के बहुत सारे के साथ समाप्त होता है, लेकिन 30 की तुलना में कम रिक्त स्थान संरक्षित किया जाना चाहिए है? वर्तमान में वे हैं।
  • उपर्युक्त जैसा ही है, लेकिन अंत में रिक्त स्थान सीमा 30 से अधिक है। (s= "Twentyseven chars long text ") की तरह - वर्तमान में सभी जगहों को अंत में हटा दिया गया है और इलिप्सिस जोड़ा गया है।
संबंधित मुद्दे