ricerca di Elixir equivalente di Ruby:Come trovare l'indice di una sottostringa?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
ricerca di Elixir equivalente di Ruby:Come trovare l'indice di una sottostringa?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
TL; DR: String.index/2 è volutamente manca perché alternative più intelligenti esistono. Molto spesso String.split/2 risolverà il problema sottostante e, in un modo, prestazioni migliori.
presumo che stiamo parlando stringhe UTF-8 qui e aspettiamo di affrontare in modo pulito con caratteri non ASCII.
L'elisir incoraggia il codice veloce. Risulta che i problemi che in genere cerchiamo di risolvere con String.index/2 possono essere risolti in un modo molto più intelligente, migliorando notevolmente le prestazioni senza compromettere la leggibilità del codice.
La soluzione più intelligente è utilizzare String.split/2 e/o altre funzioni simili del modulo String. String.split/2 funziona a livello di byte pur gestendo correttamente i grafemi. Non può andare storto perché entrambi gli argomenti sono stringhe! String.index/2 dovrebbe lavorare su un livello di grafema, cercando lentamente tutta la stringa.
Per questo motivo è improbabile che il linguaggio String.index/2 venga aggiunto alla lingua a meno che non emergano casi di utilizzo molto interessanti che non possono essere risolti in modo pulito dalle funzioni esistenti.
Vedi anche la discussione elisir-lang-core su tale questione: https://groups.google.com/forum/#!topic/elixir-lang-core/S0yrDxlJCss
Su un lato nota, Elisir è abbastanza unico nel suo supporto Unicode maturo. Mentre la maggior parte delle lingue lavora su un livello codepoint (colloquialmente "personaggi"), Elixir funziona con un concetto di livello superiore di grafemi. I grafemi sono ciò che gli utenti percepiscono come un personaggio (diciamo che è una comprensione più pratica di un "personaggio").I grafemi possono contenere più di un punto di codice (che a sua volta può contenere più di un byte).
Infine, se abbiamo davvero bisogno l'indice:
case String.split("[email protected]", "domain", parts: 2) do
[left, _] -> String.length(left)
[_] -> nil
end
Non credo che ci sia alcun involucro elisir per questo, vedi #1119.
È possibile chiamare direttamente :binary.match
fino ad allora:
iex(1)> :binary.match "[email protected]", "@"
{9, 1}
iex(2)> :binary.match "[email protected]", "domain"
{10, 6}
Il valore restituito è una tupla contenente l'indice e la lunghezza del match. È possibile estrarre solo l'indice piping in |> elem(0)
o utilizzare la corrispondenza del modello.
Si noti che :binary.match
restituisce :nomatch
se la sottostringa non viene trovata nella stringa.
È possibile ottenere l'indice di byte utilizzando :binary.match/3
{index, length} = :binary.match("aéiou", "o")
{4, 1}
Se si desidera che la posizione nella stringa quindi utilizzare:
"aéiou" |> to_char_list() |> Enum.find_index(&(&1 == ?o))
3
La documentazione del modulo String spiega la differenza tra la lunghezza di byte e la lunghezza della stringa .
È possibile utilizzare Regex.run/3
e passarlo return: :index
come opzione:
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
grazie a tutte le precedenti risposte .. –
Ha String.split/2 sono stati deprecati? Vedo solo split/1 e split/3 nei documenti più recenti. –