Wyodrębnienie ostatnich n znaków z łańcucha ruby

105

Aby uzyskać ostatnie nznaki z ciągu, założyłem, że możesz użyć

ending = string[-n..-1]

ale jeśli ciąg jest krótszy niż nlitery, otrzymasz nil.

Jakie obejścia są dostępne?

Tło : Ciągi są zwykłym ASCII i mam dostęp do Ruby 1.9.1 i używam zwykłych starych obiektów Ruby (bez frameworków internetowych).

Andrew Grimm
źródło

Odpowiedzi:

99

Tutaj masz jedną wkładkę, możesz wpisać liczbę większą niż rozmiar sznurka:

"123".split(//).last(5).to_s

Dla Ruby 1.9+

"123".split(//).last(5).join("").to_s

W przypadku ruby ​​2.0+, join zwraca łańcuch

"123".split(//).last(5).join
Gareve
źródło
19
Jeśli używasz najnowszej wersji Rubiego, możesz użyć charszamiast split.
Andrew Grimm,
1
Użyłem „12345678910” .split (//). Last (7) .join.to_s
Hard-Boiled Wonderland
@ Hard-BoiledWonderland joindziała. Myślę, że nie potrzebujesz ostatniej, to_sjeśli używasz dołączenia.
Andrew Grimm,
@AndrewGrimm Masz rację, w tym przypadku użyłem powyższego z Nokogiri n.xpath('ReferenceID').inner_text.split(//).last(7).join.to_s.to_i, potrzebowałem to_s, aby wykonać to_i, aby wyodrębnić wartość liczbową.
Hard-Boiled Wonderland
Brakuje .join - teraz zwraca tablicę ciągów. Zamiast tego powinno być "123".split(//).last(5).join(Ruby 2.0.0)
Pavel Nikolov
115

Cóż, najłatwiejsze obejście, jakie przychodzi mi do głowy, to:

ending = str[-n..-1] || str

(EDYCJA: orOperator ma niższy priorytet niż przypisanie, więc pamiętaj, aby go użyć ||).

perimosocordiae
źródło
+1 ... Myślę, że ten sposób jest łatwiejszy do odczytania niż string.reverse[0..n].reverse, co daje mi sekundę "czekaj, dlaczego on to robi?" (lub zrobiłbym to, gdybym nie czytał tego w kontekście tego pytania)
Arkaaito,
4
Dobra odpowiedź, ale ||zamiast niej orlub umieszczaj ją w nawiasach str[-n..-1] or str.
Andrew Grimm
Dobra odpowiedź, ale nie podoba mi się, że ruby ​​nie traktuje s [-inf ..- 1] tak samo jak x [0..inf]
klochner
Dzięki za zwrócenie uwagi na problem pierwszeństwa operatorów, Andrew. Dostaje mnie za każdym razem.
perimosocordiae
@perimosocordiae nie jesteś jedyny. stackoverflow.com/questions/372652/…
Andrew Grimm
51

W prostym Ruby (bez Railsów) możesz to zrobić

string.chars.last(n).join

Na przykład:

2.4.1 :009 > a = 'abcdefghij'
 => "abcdefghij"
2.4.1 :010 > a.chars.last(5).join
 => "fghij"
2.4.1 :011 > a.chars.last(100).join
 => "abcdefghij"

Jeśli używasz Ruby on Rails, możesz wywoływać metody firsti lastobiekt typu string. Te metody są preferowane, ponieważ są zwięzłe i intuicyjne.

Na przykład:

[1] pry(main)> a = 'abcdefg'                                                                                                                
 => "abcdefg"
[2] pry(main)> a.first(3)                                                                                                                   
 => "abc"
[3] pry(main)> a.last(4)                                                                                                                    
 => "defg"
Zack Xu
źródło
1
Ruby nie oznacza Railsów.
Volte
14
ending = string.reverse[0...n].reverse
Andrew Grimm
źródło
Jest to najlepsze podejście, jakie widzę na tej stronie, które spełnia wymóg możliwości podania końcowej długości znaku, która przekracza całkowitą długość ciągu.
Rob.Kachmar
1
Na przykład, jeśli zamierzasz przyjąć ostatnie 3 znaki z grupy żądeł, takich jak „abcde”, „ab” i „a”. Ta technika spowoduje, że „cde”, „ab” i „a” będą używać tego samego kodu dla każdego z nich. "abcde".reverse[0,3].reverse>>> "cde" "ab".reverse[0,3].reverse>>> "ab" "a".reverse[0,3].reverse>>> "a"
Rob.Kachmar
9

Możesz użyć następującego kodu:

string[string.length-n,string.length]
rurki
źródło
1
tylko kod - odpowiedzi nie zawsze są pomocne. wyjaśnienie, dlaczego / w jaki sposób ten kod jest poprawką, byłoby świetne
ry8806
6

Aby uzyskać ostatnie n znaków z łańcucha, możesz to zrobić

a [-n, n], jeśli a jest tablicą.

Oto przykład, jeśli chcesz.

ruby-1.9.2-p180: 006> a = "911234567890"

=> „911234567890”

rubin-1.9.2-p180: 009> a [-5,5]

=> „67890”

rubin-1.9.2-p180: 010> a [-7,7]

=> „4567890”

Sunil
źródło
Jeśli liczba jest zbyt duża, nilzwracana jest wartość, której właśnie próbowano uniknąć w tym pytaniu.
Andrew Grimm,
Dobra odpowiedź. Czysty.
Volte
Dlaczego tak się dzieje? Ma dokładnie ten sam problem, o który pytał OP, jak naprawić.
jeffdill2
5

Czy próbowałeś użyć wyrażenia regularnego?

string.match(/(.{0,#{n}}$)/)
ending=$1

Wyrażenie regularne przechwytuje tyle znaków, ile może na końcu ciągu, ale nie więcej niż n. I przechowuje to za 1 dolara.

EmFi
źródło
1

Poprawa odpowiedzi EmFi.

string[/.{,#{n}}\z/m]
sawa
źródło