2016-02-22 16 views

Odpowiedz

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 
+1

Has String.split/2 przestarzała? Widzę tylko split/1 i split/3 w najnowszych dokumentach. –

10

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.

4

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 .

5

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}] 
0
# 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 
+0

dzięki poprzedniej odpowiedzi .. –

Powiązane problemy