guillaume-lin

guillaume-lin

How to find a substring position in a string ? something like indexOf in js

I have read the docs of String module, it seems that there’s nothing like IndexOf in js which
return index of a substring in string.

Most Liked

LostKobrakai

LostKobrakai

So there’s a few layers here, which make the String module not have such a function:

Elixirs String module is about utf8 encoded binaries. So it doesn’t provide an API for general binaries no matter the encoding of the bytes in it.

For utf8 encoded binaries people have already expressed that there’s multiple ways to “count” within utf8. The smallest unit in utf8 is a codepoint. Codepoints can be combined to form graphemes. Unrelated to a specific usecase you want to default to working with graphemes. I’d suggest this excelent blog post on the matter: The Absolute Minimum Every Software Developer Must Know About Unicode in 2023 (Still No Excuses!) @ tonsky.me.

Additionally while elixir could compute you a codepoint index or a grapheme index that wouldn’t be of much use to begin with. Given a binary and a grapheme/codepoint index there’s no performant way to find where that index is in the binary. Due to the nature that codepoints and graphemes have no fixed size there’s no way to seek to such indexes. One would need to walk the binary from the beginning parsing it for utf8 to figure out where the index is pointing to – and do it again if that had been done to calculate the index in the first place. Hence String.codepoints and String.graphemes, where you get a list. Having a list makes such indexes useable.

You can also count in bytes, but if you do that with utf8 you can easily separate bytes belonging to a single grapheme or codepoint leaving you with garbage.

But what if you explicitly want to deal with bytes or don’t even have utf8 in the first place. In this case you’d want to work with OTPs :binary module, which holds apis for arbitrary binaries. And unsurprisingly it has :binary.match/2 (binary — OTP 29.0.2 (stdlib 8.0.1)), which allows you to search a binary for occurances of a pattern and give you back results in the form of {byte_index, byte_length}. Bytes can be very easily be seeked to in binaries, so it’s fine to use that here.

josevalim

josevalim

Creator of Elixir

Besides @LostKobrakai excellent’s response, can you please explain us what you are trying to do? We typically get the indexes to do something… and perhaps there is an operation for what you are already trying to do. In any case, :binary.matches/2 is likely what you want, but bear in mind it returns byte positions, not characters.

Aetherus

Aetherus

You can also use regular expression

~r/#{Regex.escape(substring)}/
|> Regex.scan(string, return: :index)

This returns the indices and lengths of all matching parts as [[{index1, length1}], [{index2, length2}], ...]

Where Next?

Popular in Questions Top

New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31194 112
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39523 209
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31307 143
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52774 488
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36432 110
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New

We're in Beta

About us Mission Statement