目錄
- 字符串
- 字符列表
- 字素和字碼點(diǎn)
- 字符串函數(shù)
- length/1
- replace/3
- duplicate/2
- split/2
- 練習(xí)
- 重組字符串
字符串
Elixir 字符串就是字節(jié)序列
iex> string = <<104,101,108,108,111>>
"hello"
使用 << >> 是告訴編譯器這個(gè)符號(hào)里面的內(nèi)容是字節(jié)。
字符列表
在 Elixir 內(nèi)部,字符串是字節(jié)序列表示的,而不是字符數(shù)組。Elixir 也有一個(gè)字符列表的類型:字符串是雙引號(hào)括起來(lái)的,而字符列表是單引號(hào)括起來(lái)的。
這兩者有什么區(qū)別呢?字符列表的每個(gè)值都是 ASCII 碼。我們來(lái)深入了解一下。
iex> char_list = 'hello'
'hello'
iex> [hd|tl] = char_list
'hello'
iex> {hd, tl}
{104, 'ello'}
iex> Enum.reduce(char_list, "", fn char, acc -> acc <> to_string(char) <> "," end)
"104,101,108,108,111,"
在使用Elixir編程的時(shí)候,通常會(huì)使用字符串,而不是字符列表。字符列表之所以存在,是因?yàn)橛行?Erlang 模塊要用到它。
字素和字碼點(diǎn)
字碼點(diǎn)就是一個(gè)或者多個(gè)字節(jié)標(biāo)識(shí)的 Unicode 字符(根據(jù) UTF-8編碼方式,每個(gè)字碼點(diǎn)或有長(zhǎng)度的不同)。ASCII 碼之外的字符一般都由多個(gè)字節(jié)表示,比如帶有波浪線或者聲調(diào)的拉丁字符 (á, ?, è) 一般都是兩個(gè)字節(jié)表示的。而亞洲語(yǔ)言的字符一般都是三個(gè)或者四個(gè)字節(jié)。字素是一個(gè)字符的表示,通常由多個(gè)字碼點(diǎn)組成。
String 模塊已經(jīng)提供了兩個(gè)方法來(lái)獲取這兩種方式的值:graphemes/1 和 codepoints/1。我們來(lái)看一下:
iex> string = "\u0061\u0301"
"á"
iex> String.codepoints string
["a", "?"]
iex> String.graphemes string
["á"]
字符串函數(shù)
這個(gè)部分我們看一下 String 模塊最常用的一些函數(shù)。本課程只會(huì)介紹其中的一部分,如果要了解所有的函數(shù),請(qǐng)參考官方 String 文檔。
length/1
返回字符串中字素的數(shù)量
iex> String.length("Hello")
5
replace/3
返回一個(gè)新的字符串,它的值是把原來(lái)某些模式替換成新的字符串得到的。
iex> String.replace("Hello", "e", "a")
"Hallo"
duplicate/2
返回重復(fù)了n遍的字符串。
iex> String.duplicate("Oh my ", 3)
"Oh my Oh my Oh my "
split/2
返回把原來(lái)字符串按照某個(gè)模式分割后的字符串列表。
iex> String.split("Hello World", " ")
["Hello", "World"]
練習(xí)
重組字符串
A 和 B 如果能通過重組變得和對(duì)方一樣,就認(rèn)為兩者是重組字符串。比如:
- A = super
- B = perus
如果我們重組 A 字符串中的元素就可以得到 B,反之亦然。
那么,怎么才能用 Elixir 判斷字符串是否為重組字符串呢?最簡(jiǎn)單的方法就是對(duì)兩個(gè)字符串的字符進(jìn)行排序,然后比較排序好的結(jié)果是否相等。
defmodule Anagram do
def anagrams?(a, b) when is_binary(a) and is_binary(b) do
sort_string(a) == sort_string(b)
end
def sort_string(string) do
string
|> String.downcase()
|> String.graphemes()
|> Enum.sort()
end
end
先看一下anagrams?/2,首先我們會(huì)檢查接受的參數(shù)是否為 binaries,這是 Elixir 檢查參數(shù)是否為字符串的方法。 然后,我們會(huì)調(diào)用把字符串按照字母表排序的函數(shù),這個(gè)函數(shù)首先把所有字符轉(zhuǎn)換成小寫,然后調(diào)用 String.graphemes 得到字符串中字素的列表。思路很清晰,對(duì)吧?
我們來(lái)通過 iex 看一下輸出結(jié)果:
iex> Anagram.anagrams?("Hello", "ohell")
true
iex> Anagram.anagrams?("María", "íMara")
true
iex> Anagram.anagrams?(3, 5)
** (FunctionClauseError) no function clause matching in Anagram.anagrams?/2
The following arguments were given to Anagram.anagrams?/2:
# 1
3
# 2
5
iex:11: Anagram.anagrams?/2
正如上面展示的,最后一次調(diào)用 anagrams?返回了 FunctionClauseError,這個(gè)錯(cuò)誤就是告訴我們模塊中沒有接受兩個(gè)非字符串的函數(shù)。這正是我們期望的結(jié)果:只接受字符串作為參數(shù),其他都不允許。