枚举Elixir中的字符串



在Elixir中,如果我有一个字符串,比如"José1 José2",我该如何枚举它?如果我尝试使用Enumfor理解,我会得到以下错误:

**(Protocol。UndefinedError(协议未为"实现枚举;José1 José2"类型为BitString

Elixir中的字符串是UTF-8编码的二进制文件。如果你想枚举一个二进制文件,它只是一个字节的集合,你需要指定如何枚举。

String.graphemes/1-这将为您提供一个字符串列表,其中每个字符串都包含一个单独的Unicode字形。这可能最接近你的意思,如果你想要每个";字符";。

iex> String.graphemes("José1 José2")
["J", "o", "s", "é", "1", " ", "J", "o", "s", "é", "2"]

String.codepoints/1-这将为您提供一个按Unicode代码点细分的字符串列表。请注意,Unicode代码点不一定能翻译成人类可读的字符。

iex> String.codepoints("José1 José2")
["J", "o", "s", "é", "1", " ", "J", "o", "s", "e", "́", "2"]

您可以看到,第一个和第二个é图元在unicode代码点方面的表示方式不同。第一个是LATIN SMALL LETTER E WITH ACUTE (U+00E9),而第二个是LATIN SMALL LETTER E (U+0065),然后是COMBINING ACUTE ACCENT (U+0301)

这就是为什么你不能简单地枚举一个字符串,因为在处理Unicode时,你必须指定你是否对字形、代码点或其他东西感兴趣。

String.to_charlist/1-为您提供一个字符串的数字Unicode代码点列表。这可以用于与使用此格式的Erlang库接口。

iex> String.to_charlist("José1 José2")
[74, 111, 115, 233, 49, 32, 74, 111, 115, 101, 769, 50]

:binary.bin_to_list/1-如果您只想枚举字节。

iex> :binary.bin_to_list("José1 José2")
[74, 111, 115, 195, 169, 49, 32, 74, 111, 115, 101, 204, 129, 50]

一旦您有了列表,您就可以使用理解或Enum模块中的任何函数对其进行枚举:

iex> for c <- String.graphemes("José1 José2"), into: "", do: c <> c
"JJoosséé11  JJoosséé22"
iex> "José1 José2" |> String.graphemes() |> Enum.join("|")
"J|o|s|é|1| |J|o|s|é|2"

也可以使用位串生成器的理解来枚举字节和代码点(但不能枚举图元(。

相当于:binary.bin_to_list/1:

iex> for <<byte <- "José1 José2">>, do: byte
[74, 111, 115, 195, 169, 49, 32, 74, 111, 115, 101, 204, 129, 50]

等效于String.to_charlist/1,通过指定二进制的类型为utf8:

iex> for <<cp::utf8 <- "José1 José2">>, do: cp
[74, 111, 115, 233, 49, 32, 74, 111, 115, 101, 769, 50]

等效于String.codepoints/1,通过指定二进制文件的类型为utf8,并将生成的代码点转换回UTF-8二进制文件:

iex> for <<cp::utf8 <- "José1 José2">>, do: <<cp::utf8>>
["J", "o", "s", "é", "1", " ", "J", "o", "s", "e", "́", "2"]

p。S.为了进一步了解字符编码,这篇2003年的博客文章非常棒:每个软件开发人员都必须绝对、积极地了解Unicode和字符集(没有借口!(。

最新更新