Ищет Elixir эквивалент Руби:Как найти индекс подстроки?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
Ищет Elixir эквивалент Руби:Как найти индекс подстроки?
"[email protected]".index("@") # => 9
"[email protected]".index("domain") # => 10
TL; DR: String.index/2 намеренно отсутствует, поскольку умнее альтернативы существуют. Очень часто String.split/2 решит основную проблему - и с лучшей эффективностью.
Я предполагаю, что мы говорим о строках UTF-8 здесь и ожидаем, что они будут иметь дело с символами, отличными от ASCII.
Эликсир поощряет быстрый код. Оказывается, проблемы, которые мы обычно пытаемся решить с помощью String.index/2, могут быть решены гораздо умнее, значительно улучшая производительность, не ухудшая читаемость кода.
Более разумное решение - использовать функции String.split/2 и/или другие аналогичные функции модуля String. String.split/2 работает на уровне байта, все еще правильно обрабатывая графемы. Это не может пойти не так, потому что оба аргумента - это строки! String.index/2 должен работать на уровне графем, медленно искажая всю строку.
По этой причине String.index/2 вряд ли будет добавлен к языку, если не появятся очень убедительные примеры использования, которые не могут быть решены с помощью существующих функций.
Смотрите также эликсир-лан-жильные дискуссии по этому вопросу: https://groups.google.com/forum/#!topic/elixir-lang-core/S0yrDxlJCss
На стороне записки, Elixir довольно уникален в своей зрелой поддержке Unicode. В то время как большинство языков работают на уровне кода (разговорные «персонажи»), Elixir работает с концепцией graphemes более высокого уровня. Графемы - это то, что пользователи воспринимают как один символ (скажем, более практическое понимание «персонажа»).Графемы могут содержать более одного кода (который, в свою очередь, может содержать более одного байта).
Наконец, если нам действительно нужно индекс:
case String.split("[email protected]", "domain", parts: 2) do
[left, _] -> String.length(left)
[_] -> nil
end
Я не думаю, что есть какая-нибудь Elixir обертка для этого, см #1119.
Вы можете позвонить :binary.match
непосредственно до тех пор:
iex(1)> :binary.match "[email protected]", "@"
{9, 1}
iex(2)> :binary.match "[email protected]", "domain"
{10, 6}
Возвращаемое значение представляет собой кортеж, содержащий индекс и продолжительность матча. Вы можете извлечь только индекс по трубопроводам в |> elem(0)
или с помощью сопоставления с образцом.
Обратите внимание, что :binary.match
возвращает :nomatch
, если подстрока не найдена в строке.
Вы можете получить индекс байт с использованием :binary.match/3
{index, length} = :binary.match("aéiou", "o")
{4, 1}
Если вы хотите место в строке используйте:
"aéiou" |> to_char_list() |> Enum.find_index(&(&1 == ?o))
3
Модуль документации String объясняет разницу между длиной байт и длиной строки ,
Вы можете использовать Regex.run/3
и передать его return: :index
как вариант:
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
благодаря всем предыдущим ответам .. –
Имеет String.split/2 устарела? Я вижу только split/1 и split/3 в самых последних документах. –