Zmieniłem odpowiedź, więc może być możliwa zmiana wybranej odpowiedzi. Sprawdź, czy możesz przyznać to odpowiedzi Jasona Stirka, ponieważ jego jest najszybsza i bardzo czytelna.
Tin Man
3
Użyj str [1 ..- 1], najszybciej zgodnie z odpowiedziami poniżej.
Achyut Rastogi,
1
Od wersji Ruby 2.5 możesz używać delete_prefixi delete_prefix!- więcej szczegółów poniżej . Nie miałem czasu na testy porównawcze, ale wkrótce to zrobię!
SRack
Aktualizacja: przetestowałem nowe metody ( delete_prefix\ delete_prefix!) i są one dość szybkie. Nie całkiem poprawiają poprzednie ulubione pod względem szybkości, ale czytelność oznacza, że są świetnymi nowymi opcjami!
1.9.3
user system total real
[0]0.8400000.0000000.840000(0.847496)
sub 1.9600000.0100001.970000(1.962767)
gsub 4.3500000.0200004.370000(4.372801)[1..-1]0.7100000.0000000.710000(0.713366)
slice 1.0200000.0000001.020000(1.020336)
length 1.1600000.0000001.160000(1.157882)
Aktualizacja w celu uwzględnienia jeszcze jednej sugerowanej odpowiedzi:
2.1.2
user system total real
[0]0.3000000.0000000.300000(0.295054)
sub 0.6300000.0000000.630000(0.631870)
gsub 2.0900000.0000002.090000(2.094368)[1..-1]0.2300000.0100000.240000(0.232846)
slice 0.3200000.0000000.320000(0.320714)
length 0.3400000.0000000.340000(0.341918)
eat!0.4600000.0000000.460000(0.452724)
reverse 0.4000000.0000000.400000(0.399465)
I jeszcze jedno użycie, /^./aby znaleźć pierwszą postać:
Oto kolejna aktualizacja szybszego sprzętu i nowszej wersji Rubiego:
2.3.1
user system total real
[0]0.2000000.0000000.200000(0.204307)[/^./]0.3900000.0000000.390000(0.387527)[/^\[/]0.3600000.0000000.360000(0.360400)
sub+0.4900000.0000000.490000(0.492083)
sub 0.4800000.0000000.480000(0.487862)
gsub 1.9900000.0000001.990000(1.988716)[1..-1]0.1800000.0000000.180000(0.181673)
slice 0.2600000.0000000.260000(0.266371)
length 0.2700000.0000000.270000(0.267651)
eat!0.4000000.0100000.410000(0.398093)
reverse 0.3400000.0000000.340000(0.344077)
Dlaczego gsub działa tak wolno?
Po wykonaniu wyszukiwania / zamiany gsubmusi sprawdzić możliwe dodatkowe dopasowania, zanim będzie mógł stwierdzić, czy zostało zakończone. subrobi tylko jedno i kończy. Rozważ, gsubże to minimum dwa subpołączenia.
Ważne jest również, aby o tym pamiętać gsubi submoże być również utrudnione przez źle napisane wyrażenie regularne, które dopasowuje się znacznie wolniej niż wyszukiwanie podłańcucha. Jeśli to możliwe, zakotwicz wyrażenie regularne, aby uzyskać jak największą szybkość. Tutaj znajdziesz odpowiedzi na Stack Overflow, które to potwierdzają, więc poszukaj więcej informacji.
Należy zauważyć, że będzie to działać tylko w Rubim 1.9. W Ruby 1.8 usunie to pierwszy bajt z łańcucha, a nie pierwszy znak, co nie jest tym, czego chce OP.
Jörg W Mittag
+1: Zawsze zapominam, że do pozycji łańcucha można przypisać nie tylko pojedynczy znak, ale także wstawić podciąg. Dzięki!
quetzalcoatl
"[12,23,987,43".delete "["
rupweb
4
To usuwa go ze wszystkich pozycji, czego nie chciał OP: „… dla pierwszego znaku?”.
Tin Man,
2
„ what about "[12,23,987,43".shift ?”? A co z "[12,23,987,43".shift NoMethodError: undefined method shift „for„ [12,23,987,43 ”: String”?
Tin Man
293
Podobne do odpowiedzi Pablo powyżej, ale środek do czyszczenia odcieni:
+1 Spójrz na wyniki testów porównawczych, które dodałem do mojej odpowiedzi. Masz najszybszy czas działania, a ponadto myślę, że jest bardzo czysty.
Tin Man
A co z wydajnością w str[1,]porównaniu z powyższymi?
Bohr
1
@Bohr: str[1,]zwraca drugi znak od zakresu 1:nil. Musisz podać rzeczywistą obliczoną długość lub coś, co gwarantuje, że będzie większa niż długość, na przykład str[1,999999](użyj oczywiście int_max), aby uzyskać cały ogon. [1..-1]jest czystszy i prawdopodobnie szybszy, ponieważ nie trzeba ręcznie operować na długości (patrz [1..length] w teście porównawczym)
quetzalcoatl
4
Bardzo fajne rozwiązanie. Nawiasem mówiąc, jeśli ktoś chce usunąć pierwsze i ostatnie znaki:str[1..-2]
pisaruk
50
Możemy do tego użyć slice:
val ="abc"=>"abc"
val.slice!(0)=>"a"
val
=>"bc"
Używając slice!możemy usunąć dowolny znak, podając jego indeks.
Ta elegancka slice!(0)naprawdę powinna być wybraną odpowiedzią, ponieważ użycie asdf[0] = '' do usunięcia pierwszego znaku jest absurdalne (tak jak używanie gsub z wyrażeniem regularnym i strzelanie w muchę z haubicy).
f055
1
Choć z pozoru może się to wydawać nieintuicyjne, []=nie wymaga tak dużej ilości kodu w języku C, gdzie slice!wymaga dodatkowej pracy. To się sumuje. Argument mógłby brzmieć „Który jest bardziej czytelny?” Uważam, że używanie jest []=czytelne, ale pochodzę z tła C -> Perl, które prawdopodobnie koloruje moje myślenie. Programiści Java prawdopodobnie pomyśleliby, że jest mniej czytelny. Albo jest to akceptowalny sposób wykonania zadania, o ile jest łatwy do zrozumienia i utrzymania oraz nie obciąża nadmiernie procesora.
Tin Man
Dobrze. Czy wiesz, jak możemy zmierzyć, jeśli funkcja zajmuje duże obciążenie procesora w ROR? czy też powinniśmy użyć różnicy czasu wykonania w mililitrach lub nanosekundach?
balanv
18
Ruby 2.5+
Od wersji Ruby 2.5 możesz używać delete_prefixlub delete_prefix!osiągać to w czytelny sposób.
W tym przypadku "[12,23,987,43".delete_prefix("[").
Korzystając z konfiguracji testowej Tin Mana, wygląda to również dość szybko (pod dwoma ostatnimi wpisami delete_pi delete_p!). Nie do końca wypina poprzednie ulubione pod względem szybkości, ale jest bardzo czytelny.
2.5.0
user system total real
[0]0.1747660.0004890.175255(0.180207)[/^./]0.3180380.0005100.318548(0.323679)[/^\[/]0.3726450.0011340.373779(0.379029)
sub+0.4602950.0015100.461805(0.467279)
sub 0.4983510.0015340.499885(0.505729)
gsub 1.6698370.0051411.674978(1.682853)[1..-1]0.1998400.0009760.200816(0.205889)
slice 0.2796610.0008590.280520(0.285661)
length 0.2683620.0003100.268672(0.273829)
eat!0.3417150.0005240.342239(0.347097)
reverse 0.3353010.0005880.335889(0.340965)
delete_p 0.2222970.0008320.223129(0.228455)
delete_p!0.2257980.0007470.226545(0.231745)
Użyłbym "[12,23,987,43".sub(/^\[+/, "")zamiast gsub(/^\[/, ""). Pierwsza pozwala silnikowi regex znaleźć wszystkie dopasowania, a następnie są one zastępowane w jednej akcji i powoduje około dwukrotną poprawę szybkości w przypadku Rubiego 1.9.3.
Tin Man
1
Skoro mamy do czynienia ze sznurkami, czy tak powinno być gsub(/\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"
W ten sposób możesz usuwać pierwszy znak łańcucha jeden po drugim.
Jeśli chcesz zachować semantykę „chop”, możesz po prostu"[12,23,987,43".reverse.chop.reverse
Chris Heald,
to całkiem spora suma wyników tylko po to, żeby rozebrać jedną postać
Pablo Fernandez
7
dlaczego nie użyć [1 ..- 1] zamiast [1..self.length]?
horseyguy
Przykład łatania małpy jest całkiem nie na to pytanie, to po prostu nieistotna i brzydka IMO.
dredozubov
3
Podziękowania dla @ the-tin-man za zestawienie wzorców!
Niestety, nie podoba mi się żadne z tych rozwiązań. Albo wymagają dodatkowego kroku, aby uzyskać wynik ( [0] = '', .strip!), albo nie są zbyt semantyczne / jasne, co się dzieje ( [1..-1]: „Hm, zakres od 1 do minus 1? Yearg?”), Albo są powolne lub długie napisz ( .gsub, .length).
To, co próbujemy, to „przesunięcie” (w żargonie tablicowym), ale zwrócenie pozostałych znaków, a nie tego, co zostało przesunięte. Użyjmy naszego Rubiego, aby było to możliwe dzięki łańcuchom! Możemy użyć operacji szybkiego nawiasu, ale nadaj jej dobrą nazwę i weź argument, aby określić, ile chcemy wydłubać z przodu:
Ale jest więcej, co możemy zrobić z tą szybką, ale nieporęczną operacją wspornika. Skoro już o tym mowa , dla kompletności napiszmy a #shifti #firstdla String (dlaczego Array miałoby mieć całą zabawę), biorąc argument, aby określić, ile znaków chcemy usunąć od początku:
classStringdef first(how_many =1)self[0...how_many]enddef shift(how_many =1)
shifted = first(how_many)self.replace self[how_many..-1]
shifted
end
alias_method :shift!,:shift
end
Ok, teraz mamy dobry, jasny sposób na wyciąganie znaków z przodu łańcucha, przy użyciu metody zgodnej z Array#firsti Array#shift(która naprawdę powinna być metodą huk ??). I możemy łatwo uzyskać zmodyfikowany ciąg za pomocą #eat!. Hm, czy powinniśmy podzielić się naszą nową eat!mocą z Array? Dlaczego nie!
delete_prefix
idelete_prefix!
- więcej szczegółów poniżej . Nie miałem czasu na testy porównawcze, ale wkrótce to zrobię!delete_prefix
\delete_prefix!
) i są one dość szybkie. Nie całkiem poprawiają poprzednie ulubione pod względem szybkości, ale czytelność oznacza, że są świetnymi nowymi opcjami!Odpowiedzi:
Preferuję użycie czegoś takiego jak:
Zawsze szukam najszybszego i najbardziej czytelnego sposobu robienia rzeczy:
Działa na moim Macu Pro:
Aktualizacja w celu uwzględnienia jeszcze jednej sugerowanej odpowiedzi:
Co skutkuje w:
I jeszcze jedno użycie,
/^./
aby znaleźć pierwszą postać:Co skutkuje w:
Oto kolejna aktualizacja szybszego sprzętu i nowszej wersji Rubiego:
Po wykonaniu wyszukiwania / zamiany
gsub
musi sprawdzić możliwe dodatkowe dopasowania, zanim będzie mógł stwierdzić, czy zostało zakończone.sub
robi tylko jedno i kończy. Rozważ,gsub
że to minimum dwasub
połączenia.Ważne jest również, aby o tym pamiętać
gsub
isub
może być również utrudnione przez źle napisane wyrażenie regularne, które dopasowuje się znacznie wolniej niż wyszukiwanie podłańcucha. Jeśli to możliwe, zakotwicz wyrażenie regularne, aby uzyskać jak największą szybkość. Tutaj znajdziesz odpowiedzi na Stack Overflow, które to potwierdzają, więc poszukaj więcej informacji.źródło
"[12,23,987,43".delete "["
what about "[12,23,987,43".shift ?
”? A co z"[12,23,987,43".shift NoMethodError: undefined method
shift „for„ [12,23,987,43 ”: String”?Podobne do odpowiedzi Pablo powyżej, ale środek do czyszczenia odcieni:
Zwróci tablicę od 1 do ostatniego znaku.
źródło
str[1,]
porównaniu z powyższymi?str[1,]
zwraca drugi znak od zakresu1:nil
. Musisz podać rzeczywistą obliczoną długość lub coś, co gwarantuje, że będzie większa niż długość, na przykładstr[1,999999]
(użyj oczywiście int_max), aby uzyskać cały ogon.[1..-1]
jest czystszy i prawdopodobnie szybszy, ponieważ nie trzeba ręcznie operować na długości (patrz [1..length] w teście porównawczym)str[1..-2]
Możemy do tego użyć slice:
Używając
slice!
możemy usunąć dowolny znak, podając jego indeks.źródło
slice!(0)
naprawdę powinna być wybraną odpowiedzią, ponieważ użycieasdf[0] = ''
do usunięcia pierwszego znaku jest absurdalne (tak jak używanie gsub z wyrażeniem regularnym i strzelanie w muchę z haubicy).[]=
nie wymaga tak dużej ilości kodu w języku C, gdzieslice!
wymaga dodatkowej pracy. To się sumuje. Argument mógłby brzmieć „Który jest bardziej czytelny?” Uważam, że używanie jest[]=
czytelne, ale pochodzę z tła C -> Perl, które prawdopodobnie koloruje moje myślenie. Programiści Java prawdopodobnie pomyśleliby, że jest mniej czytelny. Albo jest to akceptowalny sposób wykonania zadania, o ile jest łatwy do zrozumienia i utrzymania oraz nie obciąża nadmiernie procesora.Ruby 2.5+
Od wersji Ruby 2.5 możesz używać
delete_prefix
lubdelete_prefix!
osiągać to w czytelny sposób.W tym przypadku
"[12,23,987,43".delete_prefix("[")
.Więcej informacji tutaj:
Oficjalne dokumenty
https://blog.jetbrains.com/ruby/2017/10/10-new-features-in-ruby-2-5/
https://bugs.ruby-lang.org/issues/12694
Uwaga: możesz również użyć tego do usunięcia elementów z końca łańcucha za pomocą
delete_suffix
idelete_suffix!
Edytować:
Korzystając z konfiguracji testowej Tin Mana, wygląda to również dość szybko (pod dwoma ostatnimi wpisami
delete_p
idelete_p!
). Nie do końca wypina poprzednie ulubione pod względem szybkości, ale jest bardzo czytelny.źródło
Wolę to:
źródło
Jeśli zawsze chcesz usunąć nawiasy wiodące:
Jeśli chcesz tylko usunąć pierwszy znak i wiesz, że nie będzie to wielobajtowego zestawu znaków:
lub
źródło
"[12,23,987,43".sub(/^\[+/, "")
zamiastgsub(/^\[/, "")
. Pierwsza pozwala silnikowi regex znaleźć wszystkie dopasowania, a następnie są one zastępowane w jednej akcji i powoduje około dwukrotną poprawę szybkości w przypadku Rubiego 1.9.3.gsub(/\A\[/, "")
?Nieefektywna alternatywa:
źródło
Na przykład: a = "Raz, dwa, trzy"
W ten sposób możesz usuwać pierwszy znak łańcucha jeden po drugim.
źródło
Łatwy sposób:
Niesamowity sposób:
(Uwaga: wolę łatwiejszy sposób :))
źródło
"[12,23,987,43".reverse.chop.reverse
Podziękowania dla @ the-tin-man za zestawienie wzorców!
Niestety, nie podoba mi się żadne z tych rozwiązań. Albo wymagają dodatkowego kroku, aby uzyskać wynik (
[0] = ''
,.strip!
), albo nie są zbyt semantyczne / jasne, co się dzieje ([1..-1]
: „Hm, zakres od 1 do minus 1? Yearg?”), Albo są powolne lub długie napisz (.gsub
,.length
).To, co próbujemy, to „przesunięcie” (w żargonie tablicowym), ale zwrócenie pozostałych znaków, a nie tego, co zostało przesunięte. Użyjmy naszego Rubiego, aby było to możliwe dzięki łańcuchom! Możemy użyć operacji szybkiego nawiasu, ale nadaj jej dobrą nazwę i weź argument, aby określić, ile chcemy wydłubać z przodu:
Ale jest więcej, co możemy zrobić z tą szybką, ale nieporęczną operacją wspornika. Skoro już o tym mowa , dla kompletności napiszmy a
#shift
i#first
dla String (dlaczego Array miałoby mieć całą zabawę), biorąc argument, aby określić, ile znaków chcemy usunąć od początku:Ok, teraz mamy dobry, jasny sposób na wyciąganie znaków z przodu łańcucha, przy użyciu metody zgodnej z
Array#first
iArray#shift
(która naprawdę powinna być metodą huk ??). I możemy łatwo uzyskać zmodyfikowany ciąg za pomocą#eat!
. Hm, czy powinniśmy podzielić się naszą nowąeat!
mocą z Array? Dlaczego nie!Teraz możemy:
Tak lepiej!
źródło
chip()
zamiastchop()
(ichimp()
jako analogchomp()
).źródło
źródło
Korzystanie z wyrażenia regularnego:
źródło
Znajduję dobre rozwiązanie ze względu
str.delete(str[0])
na jego czytelność, choć nie mogę zaświadczyć o jego wydajności.źródło
Lista usuwa jeden lub więcej elementów z początku tablicy, nie zmienia tablicy i zwraca samą tablicę zamiast upuszczonego elementu.
źródło