Jak usunąć określone znaki z ciągu w Rubim?

85

Mam kilka ciągów, które wyglądają tak:

"((String1))"

Wszystkie mają różne długości. Jak mogę usunąć nawiasy ze wszystkich tych ciągów w pętli?

Cristiano
źródło
2
Czy usunąć nawiasy lub pierwsze dwa i ostatnie dwa znaki z „losowego” ciągu? (Właściwie losowo?)
Przywróć Monikę - notmaynard
„((String1))” [2 ...- 2] # => „String1”
Przywróć Monikę - notmaynard
1
ruby-doc.org/core-1.9.3/String.html
Przywróć Monikę - notmaynard
Pytasz o pętlę do zmiany wielu ciągów, w jaki sposób przechowywane są łańcuchy?
hirolau
Wiem, jak zrobić pętlę przez wszystkie struny. Chciałem tylko część dotyczącą manipulacji strunami, przepraszam, że sformułowałem to dziwnie
Cristiano

Odpowiedzi:

168

Wykonaj poniższe czynności, używając String#tr:

 "((String1))".tr('()', '')
 # => "String1"
Arup Rakshit
źródło
7
Istnieje również wersja destrukcyjna tr!, która modyfikuje ciąg w miejscu, na przykładmy_string.tr!(')(','')
bonh
8
Zwróć uwagę, że ta funkcja nie przycina od początku lub końca, ale całkowicie zastępuje cały tekst w ciągu.
Jordania
3
Mylące i niepoprawne. Tr nie jest funkcją przycinania, jest funkcją zastępczą. Te dwie operacje są bardzo różne.
Zane Claes
1
@ZaneClaes Yes. OP użył niewłaściwego terminu, aby wyjaśnić, czego właściwie chce PO. Odpowiedź pokazała, jak osiągnąć wynik.
Arup Rakshit
42

Jeśli chcesz tylko usunąć pierwsze dwa znaki i ostatnie dwa, możesz użyć indeksów ujemnych w ciągu:

s = "((String1))"
s = s[2...-2]
p s # => "String1"

Jeśli chcesz usunąć wszystkie nawiasy z ciągu, możesz użyć metody delete w klasie string:

s = "((String1))"
s.delete! '()'
p s #  => "String1"
jbr
źródło
8
Spowoduje to usunięcie wszystkich nawiasów, nawet tych w środku ciągu, co (pozornie) nie jest tym, czego chce OP. Jeśli tego chcemy, to jest to najbardziej eleganckie rozwiązanie.
Przywróć Monikę - notmaynard
22

Dla tych, którzy się z tym spotykają i szukają wydajności, wygląda na to #deletei #trsą mniej więcej takie same pod względem szybkości i 2-4x szybsze niż gsub.

text = "Here is a string with / some forwa/rd slashes"
tr = Benchmark.measure { 10000.times { text.tr('/', '') } }
# tr.total => 0.01
delete = Benchmark.measure { 10000.times { text.delete('/') } }
# delete.total => 0.01
gsub = Benchmark.measure { 10000.times { text.gsub('/', '') } }
# gsub.total => 0.02 - 0.04
daino3
źródło
3
Cztery lata później ... :-) stwierdzę, że jeśli podniosę twój benchmarking o kilka rzędów wielkości (1_000_000 uruchomień), że przy tym samym kodzie, którego użyłeś powyżej, usuwam działanie nieco szybciej niż tr, z usunięciem około stosunek tr wynosi 0,92, a gsub nieco mniej niż 1,5 raza usunięcia (właściwie ~ 1,46 usunięcia i ~ 1,39 tr). ymmv oczywiście. To jest w Rubim 2.6.3 na MBP 13 z 2018 roku. Dziękujemy za testowanie tych trzech metod!
likethesky
21

Używanie String#gsubz wyrażeniem regularnym:

"((String1))".gsub(/^\(+|\)+$/, '')
# => "String1"
"(((((( parentheses )))".gsub(/^\(+|\)+$/, '')
# => " parentheses "

Spowoduje to usunięcie tylko otaczających nawiasów.

"(((((( This (is) string )))".gsub(/^\(+|\)+$/, '')
# => " This (is) string "
falsetru
źródło
2
+1 dla drugiego przykładu (usuń tylko otaczające nawiasy).
Bhavneet Singh Bajwa
1

Oto jeszcze krótszy sposób osiągnięcia tego:

1) za pomocą Negative character class pattern matching

irb(main)> "((String1))"[/[^()]+/]
=> "String1"

^- Pasuje do wszystkiego, co NIE należy do klasy postaci. W klasie charachter mamy (i)

Lub z globalnym zastąpieniem „AKA: gsub”, jak wspominali inni.

irb(main)> "((String1))".gsub(/[)(]/, '')
=> "String1"
z atef
źródło
Twoje dwie odpowiedzi mają różne wyniki ((a))b. Pierwsza tylko powróci a, drugaab
Ulysse BN