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


174

उदाहरण:

[12,23,987,43

" [" को हटाने का सबसे तेज़, सबसे कुशल तरीका क्या है , शायद chop()पहले चरित्र के लिए?


1
मैंने अपना उत्तर संपादित कर दिया है, इसलिए आपके चयनित उत्तर को बदलना संभव हो सकता है। देखें कि क्या आप इसे जेसन स्टिक के जवाब के बाद से पुरस्कार दे सकते हैं क्योंकि यह सबसे तेज है, और बहुत पठनीय है।
द टीन मैन

3
नीचे दिए गए उत्तरों के अनुसार, सबसे तेज़ [1 ..- 1] का उपयोग करें।
अच्युत रस्तोगी

1
रूबी 2.5 के रूप में आप उपयोग कर सकते हैं delete_prefixऔर delete_prefix!- नीचे अधिक विवरण । मेरे पास बेंचमार्क करने का समय नहीं है, लेकिन जल्द ही करूंगा!
एसआरएके

अपडेट: मैंने नए तरीकों ( delete_prefix\ delete_prefix!) को बेंचमार्क किया है और वे बहुत तेज़ हैं। गति के लिए पिछले पसंदीदा को बिल्कुल न डालें, लेकिन पठनीयता का मतलब है कि उनके पास नए विकल्प हैं!
SRack

जवाबों:


233

मैं कुछ का उपयोग कर एहसान की तरह:

asdf = "[12,23,987,43"
asdf [0] = '' 

पी asdf
# >> "12,23,987,43"

मैं हमेशा चीजों को करने का सबसे तेज़ और सबसे पठनीय तरीका खोज रहा हूँ:

require 'benchmark'

N = 1_000_000

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }

end

मेरे मैक प्रो पर चल रहा है:

1.9.3
              user     system      total        real
[0]       0.840000   0.000000   0.840000 (  0.847496)
sub       1.960000   0.010000   1.970000 (  1.962767)
gsub      4.350000   0.020000   4.370000 (  4.372801)
[1..-1]   0.710000   0.000000   0.710000 (  0.713366)
slice     1.020000   0.000000   1.020000 (  1.020336)
length    1.160000   0.000000   1.160000 (  1.157882)

एक और सुझाए गए उत्तर को शामिल करने के लिए अद्यतन करना:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

जिसके परिणामस्वरूप:

2.1.2
              user     system      total        real
[0]       0.300000   0.000000   0.300000 (  0.295054)
sub       0.630000   0.000000   0.630000 (  0.631870)
gsub      2.090000   0.000000   2.090000 (  2.094368)
[1..-1]   0.230000   0.010000   0.240000 (  0.232846)
slice     0.320000   0.000000   0.320000 (  0.320714)
length    0.340000   0.000000   0.340000 (  0.341918)
eat!      0.460000   0.000000   0.460000 (  0.452724)
reverse   0.400000   0.000000   0.400000 (  0.399465)

और /^./पहला चरित्र खोजने के लिए एक और प्रयोग :

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('[/^./]') { N.times { "[12,23,987,43"[/^./] = '' } }
  b.report('[/^\[/]') { N.times { "[12,23,987,43"[/^\[/] = '' } }
  b.report('sub+') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[/, "") } }
  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

जिसके परिणामस्वरूप:

# >> 2.1.5
# >>               user     system      total        real
# >> [0]       0.270000   0.000000   0.270000 (  0.270165)
# >> [/^./]    0.430000   0.000000   0.430000 (  0.432417)
# >> [/^\[/]   0.460000   0.000000   0.460000 (  0.458221)
# >> sub+      0.590000   0.000000   0.590000 (  0.590284)
# >> sub       0.590000   0.000000   0.590000 (  0.596366)
# >> gsub      1.880000   0.010000   1.890000 (  1.885892)
# >> [1..-1]   0.230000   0.000000   0.230000 (  0.223045)
# >> slice     0.300000   0.000000   0.300000 (  0.299175)
# >> length    0.320000   0.000000   0.320000 (  0.325841)
# >> eat!      0.410000   0.000000   0.410000 (  0.409306)
# >> reverse   0.390000   0.000000   0.390000 (  0.393044)

यहां तेजी से हार्डवेयर पर एक और अपडेट और रूबी का एक नया संस्करण है:

2.3.1
              user     system      total        real
[0]       0.200000   0.000000   0.200000 (  0.204307)
[/^./]    0.390000   0.000000   0.390000 (  0.387527)
[/^\[/]   0.360000   0.000000   0.360000 (  0.360400)
sub+      0.490000   0.000000   0.490000 (  0.492083)
sub       0.480000   0.000000   0.480000 (  0.487862)
gsub      1.990000   0.000000   1.990000 (  1.988716)
[1..-1]   0.180000   0.000000   0.180000 (  0.181673)
slice     0.260000   0.000000   0.260000 (  0.266371)
length    0.270000   0.000000   0.270000 (  0.267651)
eat!      0.400000   0.010000   0.410000 (  0.398093)
reverse   0.340000   0.000000   0.340000 (  0.344077)

Gsub इतना धीमा क्यों है?

खोज / बदलने के बाद, gsubसंभव अतिरिक्त मैचों के लिए जांच करनी होगी , इससे पहले कि यह समाप्त हो जाए, बता सकता है। subकेवल एक और खत्म करता है। इस पर विचार करें gsubकि यह न्यूनतम दो subकॉल है।

इसके अलावा, यह याद रखना महत्वपूर्ण है gsub, और subखराब लिखित रेगेक्स द्वारा भी विकलांग किया जा सकता है जो उप-स्ट्रिंग खोज की तुलना में बहुत धीरे-धीरे मेल खाते हैं। यदि संभव हो तो रेगेक्स से सबसे अधिक गति प्राप्त करने के लिए लंगर डालें। स्टैक ओवरफ्लो पर यहाँ उत्तर हैं कि यदि आप अधिक जानकारी चाहते हैं तो आसपास खोज करें।


34
यह ध्यान रखना महत्वपूर्ण है कि यह केवल रूबी 1.9 में काम करेगा। रूबी 1.8 में, यह पहले बाइट को स्ट्रिंग से हटा देगा , कि पहला चरित्र, जो ओपी चाहता है वह नहीं है।
जॉर्ग डब्ल्यू मित्तग

+1: मैं हमेशा यह भूल जाता हूं कि एक स्ट्रिंग-पोजिशन में आप न केवल एक कैरेक्टर को असाइन कर सकते हैं, बल्कि एक सबरिंग भी डाल सकते हैं। धन्यवाद!
quetzalcoatl

"[12,23,987,43".delete "["
रु। १b

4
वह इसे सभी पदों से हटा देता है, जो कि ओपी नहीं चाहता था: "... पहले चरित्र के लिए?"।
टीन मैन

2
" what about "[12,23,987,43".shift ?"? "[12,23,987,43".shift NoMethodError: undefined method शिफ्ट '' [12,23,987,43 "के बारे में क्या : स्ट्रिंग`?
टीन मैन

293

ऊपर पाब्लो के जवाब के समान, लेकिन एक छाया क्लीनर:

str[1..-1]

1 से अंतिम वर्ण में सरणी लौटाएगा।

'Hello World'[1..-1]
 => "ello World"

13
+1 मैंने अपने उत्तर में जोड़े गए बेंचमार्क परिणामों पर एक नज़र डालें। आपको सबसे तेज़ रन-टाइम मिला है, साथ ही मुझे लगता है कि यह बहुत साफ है।
टीन मैन

str[1,]ऊपर की तुलना में प्रदर्शन के बारे में क्या ?
बोह्र।

1
@ बोहर: str[1,]सीमा के बाद से आप दूसरा वर्ण लौटाते हैं 1:nil। आपको str[1,999999]संपूर्ण पूंछ प्राप्त करने के लिए वास्तविक गणना की गई लंबाई, या लंबाई से अधिक होने की गारंटी दी गई चीज़ों की आवश्यकता होगी, जैसे, (int_max का उपयोग करें)। [1..-1]क्लीनर और शायद तेज है, क्योंकि आपको मैन्युअल रूप से लंबाई पर काम करने की ज़रूरत नहीं है (बेंचमार्क में [1..length] देखें)
quetzalcoatl

4
बहुत अच्छा उपाय है। वैसे अगर कोई पहले और आखिरी पात्रों को हटाना चाहता है:str[1..-2]
pisaruk

50

हम ऐसा करने के लिए स्लाइस का उपयोग कर सकते हैं:

val = "abc"
 => "abc" 
val.slice!(0)
 => "a" 
val
 => "bc" 

इसका उपयोग करके slice!हम किसी भी वर्ण को उसके सूचकांक को निर्दिष्ट करके हटा सकते हैं।


2
यह सुरुचिपूर्ण slice!(0)वास्तव में चयनित उत्तर होना चाहिए, जैसा asdf[0] = '' कि पहले चरित्र को हटाने के लिए उपयोग करना हास्यास्पद है (जैसे रेगेक्स के साथ गसूब का उपयोग करना और हॉवित्ज़र के साथ एक मक्खी की शूटिंग करना)।
f055

1
हालांकि यह सतह पर एकतरफा लग सकता है, []=इसके लिए अधिक अंतर्निहित सी कोड की आवश्यकता नहीं होती है, जहां slice!अतिरिक्त काम की आवश्यकता होती है। वह जुड़ जाता है। तर्क "जो अधिक पठनीय है?" मैं []=पढ़ने योग्य का उपयोग कर पाता हूं , लेकिन मैं एक C -> पर्ल पृष्ठभूमि से आता हूं जो शायद मेरी सोच को रंग देता है। जावा डेवलपर्स शायद सोचते हैं कि यह कम पठनीय है। या तो कार्य को पूरा करने का एक स्वीकार्य तरीका है जब तक यह आसानी से समझा और बनाए रखा जा सकता है और सीपीयू को लोड नहीं करता है।
टीन मैन

ठीक। क्या आप जानते हैं कि यदि कोई फ़ंक्शन ROR में अधिक CPU लोड लेता है तो हम कैसे माप सकते हैं? या हमें मिलि या नैनोसेकंड में निष्पादन समय अंतर का उपयोग करना चाहिए?
बालनव

18

रूबी 2.5+

रूबी 2.5 के रूप में आप इसे पढ़ने योग्य तरीके से उपयोग delete_prefixया delete_prefix!प्राप्त कर सकते हैं ।

इस मामले में "[12,23,987,43".delete_prefix("[")

अधिक जानकारी यहाँ:

'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"

NB आप इसके साथ स्ट्रिंग के अंत से आइटम निकालने के लिए भी इसका उपयोग कर सकते हैं delete_suffixऔरdelete_suffix!

'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"

संपादित करें:

टिन मैन के बेंचमार्क सेटअप का उपयोग करते हुए, यह बहुत जल्दी दिखता है (पिछले दो प्रविष्टियों के तहत delete_pऔर delete_p!)। हालांकि गति के लिए पिछले फव्वारे को काफी नहीं लगाया जाता है, हालांकि यह बहुत ही पठनीय है।

2.5.0
              user     system      total        real
[0]       0.174766   0.000489   0.175255 (  0.180207)
[/^./]    0.318038   0.000510   0.318548 (  0.323679)
[/^\[/]   0.372645   0.001134   0.373779 (  0.379029)
sub+      0.460295   0.001510   0.461805 (  0.467279)
sub       0.498351   0.001534   0.499885 (  0.505729)
gsub      1.669837   0.005141   1.674978 (  1.682853)
[1..-1]   0.199840   0.000976   0.200816 (  0.205889)
slice     0.279661   0.000859   0.280520 (  0.285661)
length    0.268362   0.000310   0.268672 (  0.273829)
eat!      0.341715   0.000524   0.342239 (  0.347097)
reverse   0.335301   0.000588   0.335889 (  0.340965)
delete_p  0.222297   0.000832   0.223129 (  0.228455)
delete_p!  0.225798   0.000747   0.226545 (  0.231745)

17

यह मेरे लिए ज़्यादा प्रधान है:

str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43

3
आप उन्हें दोहराने से पहले अन्य उत्तरों की जांच करना चाह सकते हैं। यह पहले से ही stackoverflow.com/
टिन मैन

14

यदि आप हमेशा अग्रणी कोष्ठक पट्टी करना चाहते हैं:

"[12,23,987,43".gsub(/^\[/, "")

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

"[12,23,987,43"[1..-1]

या

"[12,23,987,43".slice(1..-1)

1
मैं "[12,23,987,43".sub(/^\[+/, "")इसके बजाय का उपयोग करेंगे gsub(/^\[/, "")। पहले रेगेक्स इंजन को सभी मैचों का पता लगाने देता है, फिर उन्हें एक एक्शन में बदल दिया जाता है और रूबी 1.9.3 के साथ गति में 2x सुधार के बारे में परिणाम देता है।
टीन मैन

1
जब से हम तार के साथ काम कर रहे हैं, यह होना चाहिए gsub(/\A\[/, "") ?
सागर पंड्या


4

उदाहरण के लिए: a = "एक दो तीन"

1.9.2-p290 > a = "One Two Three"
 => "One Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "ne Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "e Two Three" 

1.9.2-p290 > a = a[1..-1]
 => " Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "wo Three" 

इस तरह आप स्ट्रिंग के पहले एक एक अक्षर को हटा सकते हैं।


3
यह जेसन स्टर्क के जवाब के समान है, केवल उसके कई महीने पहले प्रस्तुत किया गया था।
द टीन मैन

3

आसान तरीका:

str = "[12,23,987,43"

removed = str[1..str.length]

बहुत बढ़िया तरीका:

class String
  def reverse_chop()
    self[1..self.length]
  end
end

"[12,23,987,43".reverse_chop()

(नोट: आसान तरीका पसंद करें :))


1
यदि आप "काट" शब्दार्थ को संरक्षित करना चाहते हैं, तो आप बस"[12,23,987,43".reverse.chop.reverse
क्रिस हील्ड

एक बहुत बड़ा प्रदर्शन ओवरहेड है जो सिर्फ एक चार पट्टी करने के लिए है
पाब्लो फर्नांडीज

7
क्यों नहीं [1.- 1] के बजाय [1..self.length] का उपयोग करें?
घोड़ागुडी

इस सवाल के लिए मंकी पैचिंग का उदाहरण बहुत अच्छा है, यह सिर्फ अप्रासंगिक और बदसूरत आईएमओ है।
dredozubov

3

बेंचमार्क को एक साथ रखने के लिए @-टिन-मैन का धन्यवाद!

काश, मैं वास्तव में उन समाधानों में से किसी को पसंद नहीं करता। या तो उन्हें परिणाम प्राप्त करने के लिए एक अतिरिक्त कदम की आवश्यकता होती है ( या [0] = '', .strip!) या वे बहुत शब्दार्थ / स्पष्ट नहीं हैं कि क्या हो रहा है ( [1..-1]: "उम, 1 से नकारात्मक 1 वर्ष की सीमा? वर्ष?"), या वे धीमे या लंबे हैं? लिखना ( .gsub, .length)।

हम जो प्रयास कर रहे हैं वह एक 'शिफ्ट' (ऐरे पैरलेंस में) है, लेकिन जो शिफ्ट किया गया था, उसके बजाए शेष पात्रों को वापस करना। चलो स्ट्रिंग्स के साथ इसे संभव बनाने के लिए हमारी रूबी का उपयोग करें! हम तेजी से ब्रैकेट ऑपरेशन का उपयोग कर सकते हैं, लेकिन इसे एक अच्छा नाम दे सकते हैं, और यह बताने के लिए एक आर्ग ले सकते हैं कि हम सामने वाले को कितना दम देना चाहते हैं:

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

लेकिन वहाँ अधिक है कि हम उस तेजी से-लेकिन-अस्पष्ट ब्रैकेट ऑपरेशन के साथ कर सकते हैं। जब हम इस पर हैं, पूर्णता के लिए, आइए एक स्ट्रिंग के लिए #shiftऔर #first(क्यों Array में सभी fun‽‽ होना चाहिए) लिखें, यह निर्दिष्ट करने के लिए कि हम कितने वर्णों को शुरू से हटाना चाहते हैं:

class String
  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

ठीक है, अब हमारे पास एक स्ट्रिंग के सामने से पात्रों को खींचने का एक अच्छा स्पष्ट तरीका है, एक विधि के साथ संगत है Array#firstऔर Array#shift(जो वास्तव में एक धमाके की विधि होनी चाहिए?)। और हम संशोधित स्ट्रिंग को आसानी से प्राप्त कर सकते हैं #eat!। हम्म, क्या हमें eat!ऐरे के साथ अपनी नई आईएनजी शक्ति साझा करनी चाहिए ? क्यों नहीं!

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

अब हम कर सकते हैं:

> str = "[12,23,987,43" #=> "[12,23,987,43"
> str.eat!              #=> "12,23,987,43"
> str                   #=> "12,23,987,43"

> str.eat!(3)           #=> "23,987,43"
> str                   #=> "23,987,43"

> str.first(2)          #=> "23"
> str                   #=> "23,987,43"

> str.shift!(3)         #=> "23,"
> str                   #=> "987,43"

> arr = [1,2,3,4,5]     #=> [1, 2, 3, 4, 5] 
> arr.eat!              #=> [2, 3, 4, 5] 
> arr                   #=> [2, 3, 4, 5] 

वह बेहतर है!


2
मुझे याद है कि इस तरह के एक समारोह के chip()बजाय chop()(और chimp()के एनालॉग के रूप में chomp()) के बारे में पर्ल मंचों में एक चर्चा सालों पहले हुई थी ।
मार्क थॉमस

2
str = "[12,23,987,43"

str[0] = ""

7
यह ध्यान रखना महत्वपूर्ण है कि यह केवल रूबी 1.9 में काम करेगा। रूबी 1.8 में, यह पहले बाइट को स्ट्रिंग से हटा देगा , कि पहला चरित्र, जो ओपी चाहता है वह नहीं है।
जोर्ग डब्ल्यू मित्तग



0

मुझे str.delete(str[0])इसकी पठनीयता के लिए एक अच्छा समाधान मिल गया है, हालांकि मैं इसे प्रदर्शन के लिए स्वीकार नहीं कर सकता।


0

सूची = [१,२,३,४] सूची। क्रॉप (१)

# => [2,3,4]

सूची सरणी की शुरुआत से एक या एक से अधिक तत्वों को गिराती है, सरणी को म्यूट नहीं करती है, और गिराए गए तत्व के बजाय सरणी को ही वापस कर देती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.