Dusty

Dusty

Best way to compare graphemes to codepoints from a binary pattern match

I am trying to compare the first character in a very long input string (like the text of a book) to some arbitrary character in a shorter string. The algorithm has an index for a grapheme in the shorter string, and just wants to check equality: Is the first character of my long string equal to the grapheme or not? I am trying to avoid doing something expensive under the hood, like calling String.graphemes/1 on the longer string. But I am having trouble figuring out the best way to compare the codepoint I get from binary pattern matching to the grapheme I get from other String methods.

To give a simple example:

def my_func(<<first::utf8, _rest::binary>> = _long_string) do
  last = String.at("string", 5)
  first == last
end

my_func("green")
# => false

I understand that basically this function is doing:

?g == "g"

so it makes sense that it returns false. But I am struggling to find the most efficient way to make this comparison.

I can do something like:

def my_func(<<first::utf8, _rest::binary>> = _long_string) do
  [last] = String.to_charlist(String.at("string", 5))
  first == last
end

my_func("green")
# => true

It works - but it feels like I should be able to do better :slight_smile:. What I wanted to do was use the codepoint operator on the variable, like first == ?last, but it didn’t take long for me to understand that won’t fly.

My impression is that String.next_grapheme/1 and friends are going to process the whole string just to give me one value. Is that the case? Seems like using Stream won’t help if it requires me to process the long string into an enumerable first.

Should I stick with my second method above, or is there a better way?

Marked As Solved

Eiji

Eiji

@Dusty How about replacing your function body to that code:

String.ends_with?("string", <<first::utf8>>)

Also Liked

LostKobrakai

LostKobrakai

Charlists and binaries don’t really have things in common. Your code just happens to extract the codepoint for ?s from the binary. If you’d segment by a different type things might look different:

iex(16)> IO.inspect("string", base: :binary)
<<0b1110011, 0b1110100, 0b1110010, 0b1101001, 0b1101110, 0b1100111>>
"string"
iex(17)> IO.inspect("string", base: :hex)
<<0x73, 0x74, 0x72, 0x69, 0x6E, 0x67>>
"string"

Binaries are just a list of bytes. To apply meaning you’ll need to know how to interpret the bytes to something higher level. Charlists on the other hand are always a list of intergers for the spec: [0..0x10FFFF].

Eiji

Eiji

@Dusty Simply take a look at Kernel.SpecialForms.<<>>/1 documentation.

The utf8 , utf16 , and utf32 types are for Unicode code points. They can also be applied to literal strings and charlists:

iex> <<"foo"::utf16>>
<<0, 102, 0, 111, 0, 111>>
iex> <<"foo"::utf32>>
<<0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 0, 111>>

Where Next?

Popular in Questions Top

sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
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
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
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
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
yawaramin
In the Dialyzer docs ( dialyzer — OTP 29.0.2 (dialyzer 6.0.1) ), there is a way to turn off a specific warning for a function: -dialyzer...
New

Other popular topics Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
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
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 39297 209
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

Latest on Elixir Forum

We're in Beta

About us Mission Statement