Szukasz Elixir odpowiednik Ruby:Jak znaleźć indeks podciągu?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
Szukasz Elixir odpowiednik Ruby:Jak znaleźć indeks podciągu?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
TL; DR: String.index/2 jest celowo brakuje ponieważ istnieje inteligentniejsze alternatywy. Bardzo często String.split/2 rozwiąże podstawowy problem - i ze znacznie lepszą wydajnością.
Zakładam, że mówimy UTF-8 ciągi tutaj i oczekiwać na czysto czynienia ze znakami spoza ASCII.
Eliksir zachęca do szybkiego kodu. Okazuje się, że problemy, które zwykle próbujemy rozwiązać za pomocą String.index/2, można rozwiązać w znacznie inteligentniejszy sposób, znacznie poprawiając wydajność bez pogarszania czytelności kodu.
Sprytniejszym rozwiązaniem jest użycie String.split/2 i/lub innych podobnych funkcji modułu String. String.split/2 działa na poziomie bajtów, nadal poprawnie obsługując grafemy. Nie może się nie udać, ponieważ oba argumenty są ciągami! String.index/2 musiałby pracować na poziomie grapemograficznym, powoli szukając w całym łańcuchu.
Z tego powodu mało prawdopodobne jest dodanie ciągu String.index/2 do języka, chyba że pojawią się bardzo istotne przypadki użycia, których nie można w łatwy sposób rozwiązać za pomocą istniejących funkcji.
Zobacz również dyskusję eliksir-lang-core w tej sprawie: https://groups.google.com/forum/#!topic/elixir-lang-core/S0yrDxlJCss
Na marginesie, Elixir jest dość wyjątkowa w swojej dojrzałej wsparcie Unicode. Podczas gdy większość języków pracuje na poziomie współrzędnych (potocznie "postacie"), Elixir pracuje z wyższą koncepcją grafem. Gragremy są tym, co użytkownicy postrzegają jako jedną postać (powiedzmy, że jest to bardziej praktyczne rozumienie "postaci").Gragrhemes może zawierać więcej niż jeden punkt kodowy (który z kolei może zawierać więcej niż jeden bajt).
Wreszcie, jeśli naprawdę musimy indeksu:
case String.split("[email protected]", "domain", parts: 2) do
[left, _] -> String.length(left)
[_] -> nil
end
Nie sądzę, istnieje jakikolwiek wrapper Eliksir na ten temat, zobacz #1119.
Można zadzwonić :binary.match
bezpośrednio do tej pory:
iex(1)> :binary.match "[email protected]", "@"
{9, 1}
iex(2)> :binary.match "[email protected]", "domain"
{10, 6}
Wartością zwracaną jest krotka zawierająca indeks i długość meczu. Możesz wyodrębnić indeks tylko za pomocą linii |> elem(0)
lub dopasowując do wzorca.
Należy pamiętać, że :binary.match
zwraca :nomatch
, jeśli podciąg nie znajduje się w łańcuchu.
można uzyskać indeks bajt korzystając :binary.match/3
{index, length} = :binary.match("aéiou", "o")
{4, 1}
Jeśli chcesz lokalizację w łańcuchu następnie użyć:
"aéiou" |> to_char_list() |> Enum.find_index(&(&1 == ?o))
3
String dokumentacja moduł wyjaśnia różnicę między bajt długości i długości strun .
Można użyć Regex.run/3
i przekazać go return: :index
jako opcja:
iex(5)> [{start, len}] = Regex.run(~r/abc/, " abc ", return: :index)
[{1, 3}]
# index (as INSTR from basic...)
...
import IO, except: [inspect: 1]
puts index "algopara ver", "ver"
def index(mainstring, searchstring) do
tuple = (:binary.match mainstring, searchstring)
if tuple === :nomatch do
0
else
elem(tuple,0)
end
end
...
9
dzięki poprzedniej odpowiedzi .. –
Has String.split/2 przestarzała? Widzę tylko split/1 i split/3 w najnowszych dokumentach. –