Stringモジュールで遊んでみたシリーズ④ -String.length ~ String.next_grapheme の紹介

こんにちは！
プログラミング未経験文系出身、Elixirの国に迷い込んだ？！見習いアルケミストのaliceと申します。
今回はStringモジュールについて学んだことをまとめます。

# 目次
1.[Stringモジュールで遊んでみたシリーズ① -String.at ~ String.chunk の紹介](https://qiita.com/Alicesky2127/items/47fffc38711d7369beee)
2.[Stringモジュールで遊んでみたシリーズ② -String.codepoints ~ String.ends_with? の紹介](https://qiita.com/Alicesky2127/items/5db34c69993d35b8f3a7)
3.[Stringモジュールで遊んでみたシリーズ③ -String.equivalent? ~ String.last の紹介](https://qiita.com/Alicesky2127/items/37aa8e62e8e1d5fef3b6)
4.Stringモジュールで遊んでみたシリーズ④ -String.length ~ String.next_grapheme の紹介(本記事)
5.[Stringモジュールで遊んでみたシリーズ⑤ -String.next_grapheme_size ~ String.printable? の紹介](https://qiita.com/Alicesky2127/items/a315148e966c9f103a7c)
6.[Stringモジュールで遊んでみたシリーズ⑥ -String.replace ~ String.replace_suffix の紹介](https://qiita.com/Alicesky2127/items/94a77afe270587ed21a9)
7.[Stringモジュールで遊んでみたシリーズ⑦ -String.replace_trailing ~ String.split の紹介](https://qiita.com/Alicesky2127/items/1a8e9c92fa758d0b1337)
8.[Stringモジュールで遊んでみたシリーズ⑧ -String.split_at ~ String.to_charlist の紹介](https://qiita.com/Alicesky2127/items/40e74cd622653796df5c)
9.[Stringモジュールで遊んでみたシリーズ⑨ -String.to_existing_atom ~ String.trim の紹介](https://qiita.com/Alicesky2127/items/9bf2b1effc3b68819ac2)
10.[Stringモジュールで遊んでみたシリーズ10 -String.trim_leading ~ String.valid? の紹介](https://qiita.com/Alicesky2127/items/b8310a3f5fc5b040ca78)


# 目的 
Stringモジュールに含まれる関数を触って機能を理解したい

https://hexdocs.pm/elixir/String.html

## 実行環境
Windows 11 ＋ WSL2 ＋ Ubuntu 22.04
Elixir v1.17.3
Erlang v27.0


# String.lengthとは
`String.length(string)`は`string`の文字数を返します。
文字数は書記素ベースで1文字とカウントします。

## 例
```diff_elixir:iex
String.length("elixir")
```
```
6
```

## 余談
`String.length`は`String.graphemes(string) |> Enum.count()`と同じ処理と理解しています

### `String.length`を使用した場合
※"é"はU+0065 と U+0301 の結合文字列です。[^1]
```diff_elixir:iex
String.length("é")
```
```
1
```

### `String.length`を使用しない場合
```diff_elixir:iex
String.graphemes("é") |> Enum.count()
```
```
1
```

# String.match?とは
`String.match?(string, regex)`は`string`に対して`regex`にマッチするか否かをチェックします。
この関数と同様の機能を提供するものとして下記があります
　・`=~` （テキストベースのマッチ演算子）
　・`Regex.match?(regex, string)`

## 例
```diff_elixir:iex
String.match?("foo", ~r/foo/)
```
```
true
```

```diff_elixir:iex
String.match?("bar", ~r/foo/)
```
```
false
```


# String.myers_differenceとは
`String.myers_difference(string1, string2)`は`string1`と`string2`の差分を比較します。
`string1`を`string2`と一致させるために必要な編集の差分を出力します。

## 例
```diff_elixir:iex
string1 = "Tanaka Takumi"
string2 = "Tanaoka Takeshi"
String.myers_difference(string1, string2)
```
```
[eq: "Tana", ins: "o", eq: "ka Tak", del: "um", ins: "esh", eq: "i"]
```
・キーが`eq:`のときはequal、`string1`を`string2`で同じ箇所。編集不要
・キーが`ins:`のときはinsert、`string1`に対して値の文字列を挿入する編集が入る
・キーが`del:`のときはdelete、`string1`に対して値の文字列を削除する編集が入る


# String.next_codepointとは
`String.next_codepoint(arg)`は`arg`内の先頭のコードポイントと残りの文字列のタプルを返します。
## 例
```diff_elixir:iex
String.next_codepoint("olá")
```
```
{"o", "lá"}
```

### `arg`がUTF-8でエンコードされた文字列ではないバイトシーケンスで始まる場合
出力は最初のバイトを含むバイナリ型で返される

※下記の`\x80`はUTF-8でエンコードされた文字列ではない
```diff_elixir:iex
invalid = "\x80\x80hogehoge"
{_, rest} = String.next_codepoint(invalid)
```
```
{<<128>>, <<128, 104, 111, 103, 101, 104, 111, 103, 101>>}
```

```diff_elixir:iex
String.next_codepoint(rest)
```
```
{<<128>>, "hogehoge"}
```

# String.next_graphemeとは
`String.next_codepoint(string)`は`string`内の先頭の書記素と残りの文字列のタプルを返します。

## 例
※"é"はU+0065 と U+0301 の結合文字列です。[^1]

```diff_elixir:iex
String.next_grapheme("é")
```
```
{"é", ""} #書記素ベースの場合、結合文字列を1文字と認識している
```

※比較用
```diff_elixir:iex
String.next_codepoint("é")
```
```
{"e", "́ "} #コードポイントベースの場合、結合文字列を2文字と認識している
```

# ～Elixirの国のご案内～
↓Elixirって何ぞや？と思ったらこちらもどぞ。Elixirは先端のアレコレをだいたい全部できちゃいます:laughing::sparkles::sparkles:

https://qiita.com/piacerex/items/09876caa1e17169ec5e1

↓ゼロからElixirを始めるなら「エリクサーチ」がおすすめ！私もエンジニア未経験から学習中です。

https://elixir-lang.info/topics/entry_column


↓[We Are The Alchemists, my friends!:bouquet:](https://qiita.com/torifukukaiou/items/6bcd5bbb80df9e594e9e "Awesome-san's Awesome article")[^10]
Elixirコミュニティは本当に優しくて温かい人たちばかり！
私が挫折せずにいられるのもこの恵まれた環境のおかげです。
まずは気軽にコミュニティを訪れてみてください。[^11]


https://speakerdeck.com/elijo/elixirkomiyunitei-falsebu-kifang-guo-nei-onrainbian


[^1]:書記素とコードポイントの違い https://qiita.com/Alicesky2127/items/8dcb4612dd3f6ba6f59b

[^10]: @torifukukaiouさんのAwesomeな名言をお借りしました。Elixirコミュニティを一言で表すと、これに尽きます。


[^11]: @kn339264さんの素敵なスライドをお借りしました。Elixirコミュニティはいろんな形で活動中！