Unicode 如何检查grapheme是否是一封信?

Unicode 如何检查grapheme是否是一封信?,unicode,internationalization,elixir,Unicode,Internationalization,Elixir,我如何检查grapheme是否是一个字母(或者经常用于单词中的东西,比如象形文字) 查看Elixir的String文档后,我看到的唯一方法是检查String.downcase和String.upcase是否返回相同的字符串。如果他们这样做了,那么字位就不是单词中使用的东西 我就是这样做的,但肯定有更简单的方法吗 defmodule Words do defp all_letters_uppercase?(string) do String.upcase(string) == stri

我如何检查grapheme是否是一个字母(或者经常用于单词中的东西,比如象形文字)

查看Elixir的
String
文档后,我看到的唯一方法是检查
String.downcase
String.upcase
是否返回相同的字符串。如果他们这样做了,那么字位就不是单词中使用的东西

我就是这样做的,但肯定有更简单的方法吗

defmodule Words do
  defp all_letters_uppercase?(string) do
    String.upcase(string) == string
  end

  defp all_letters_downcase?(string) do
    String.downcase(string) == string
  end

  defp contains_letter?(string) do
    not (all_letters_uppercase?(string) and all_letters_downcase?(string))
  end

  def single_grapheme?(string) do
    with graphemes = String.graphemes(string)
    do
      length(graphemes) == 1 and hd(graphemes) == string
    end
  end

  @doc """
  Check whether string is a single letter.
  """
  def letter?(string) do
    single_grapheme?(string) and contains_letter?(string)
  end
end
更新:我的代码不适用于日文字母

iex(35)> Words.letter?("グ")            
false

您可以使用正则表达式检查某些unicode功能,其中一个是
\p{Letter}
,简称
\p{L}
。您可能需要添加一个
\p{Mark}*
,或
\p{M}*
,以同时匹配以下多个组合变音符号。这将与
String.graphemes/1
中的逻辑紧密匹配。确保在正则表达式之后添加
u
修饰符以启用这些Unicode功能。例如:

iex> String.match?("グ", ~r/\A\p{L}\p{M}*\z/u)
true

另请参见“Unicode字符属性”一节和。

这似乎工作正常:

defmodule Words do
  def letter?(string) do
    Regex.match?(~r/^\p{L}$/fu, string)
  end
end


iex(51)> Words.letter?("a")
true
iex(52)> Words.letter?("é")
true
iex(53)> Words.letter?("グ")
true
iex(54)> Words.letter?("aa")
false
iex(55)> Words.letter?("1") 
false
iex(56)> Words.letter?("-")
false
iex(57)> Words.letter?("") 
false
iex(58)> Words.letter?(" ")
false
iex(59)> Words.letter?("éé")
false
iex(60)> Words.letter?("a ")
false

仅限我的2个字符:如果要匹配整个输入字符串,还可以使用
\A
(字符串开头)和
\z
(字符串结尾)锚。我发现
^
(行首)加上
$
(行尾)再加上
f
(第一行)修饰符表达的意图不太清晰。@PatrickOscity很有趣,我甚至不知道这些锚存在。出于某种原因,每个人和他们的狗都会使用
^
$
。这似乎与包含字母和组合字符的多码点图形不匹配,例如
Words.letter?(“g̉”)#=>false
,而问题中的代码返回true。您可以使用
\p{L}\p{M}*
匹配任意数量的下列组合变音符号。@CrabMan组合标记可以任意组合,形成字符和变音符号的任意组合。但是,许多常用组合也可用于als预合成字符。或者,您只能使用
String.normalize(输入:nfc)
匹配预合成字符,然后只匹配
\p{L}
。不过,我认为匹配组合标记也没什么坏处
String.graphemes/1
也将这些字符视为一个字符,因此您将与此逻辑非常匹配。还编辑了我的答案,包括合并分数。