2016-04-13 70 views
4

如何檢查字形是否是字母(或者像文字中常用的象形文字)?如何檢查字形是否是字母?

查看Elixir的String文檔後,我看到的唯一方法是檢查String.downcaseString.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 

回答

8

您可以使用正則表達式來檢查一些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 

另見http://erlang.org/doc/man/re.html,關於 「Unicode字符屬性」 和http://www.regular-expressions.info/unicode.html#grapheme部分。

0

這似乎是工作的罰款:

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 
+0

只是我的2¢:如果你想匹配你也可以使用'\ A'(字符串的開頭)的整個輸入字符串和'\ z' (字符串的結尾)錨。我發現'^'(行首)加上'$'(行結尾)加上'f'(第一行)修飾符以更清楚地表達意圖。 –

+0

@PatrickOscity有趣,我甚至不知道那些錨點存在。出於某種原因,每個人和他們的狗都使用'^'和'$'。 – CrabMan

+1

這似乎不匹配包含字母和組合字符的多碼點字形,例如, 'Words.letter?(「g̈」)#=> false',而您的問題中的代碼返回true。 – Dogbert

相關問題