Elixir-字符串

目录

  • 字符串
  • 字符列表
  • 字素和字码点
  • 字符串函数
    • length/1
    • replace/3
    • duplicate/2
    • split/2
  • 练习
    • 重组字符串

字符串

Elixir 字符串就是字节序列

iex> string = <<104,101,108,108,111>>
"hello"

使用 << >> 是告诉编译器这个符号里面的内容是字节。

字符列表

在 Elixir 内部,字符串是字节序列表示的,而不是字符数组。Elixir 也有一个字符列表的类型:字符串是双引号括起来的,而字符列表是单引号括起来的。

这两者有什么区别呢?字符列表的每个值都是 ASCII 码。我们来深入了解一下。

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编程的时候,通常会使用字符串,而不是字符列表。字符列表之所以存在,是因为有些 Erlang 模块要用到它。

字素和字码点

字码点就是一个或者多个字节标识的 Unicode 字符(根据 UTF-8编码方式,每个字码点或有长度的不同)。ASCII 码之外的字符一般都由多个字节表示,比如带有波浪线或者声调的拉丁字符 (á, ñ, è) 一般都是两个字节表示的。而亚洲语言的字符一般都是三个或者四个字节。字素是一个字符的表示,通常由多个字码点组成。

String 模块已经提供了两个方法来获取这两种方式的值:graphemes/1codepoints/1。我们来看一下:

iex> string = "\u0061\u0301"
"á"

iex> String.codepoints string
["a", "́"]

iex> String.graphemes string
["á"]

字符串函数

这个部分我们看一下 String 模块最常用的一些函数。本课程只会介绍其中的一部分,如果要了解所有的函数,请参考官方 String 文档。

length/1

返回字符串中字素的数量

iex> String.length("Hello")
5

replace/3

返回一个新的字符串,它的值是把原来某些模式替换成新的字符串得到的。

iex> String.replace("Hello", "e", "a")
"Hallo"

duplicate/2

返回重复了n遍的字符串。

iex> String.duplicate("Oh my ", 3)
"Oh my Oh my Oh my "

split/2

返回把原来字符串按照某个模式分割后的字符串列表。

iex> String.split("Hello World", " ")
["Hello", "World"]

练习

重组字符串

A 和 B 如果能通过重组变得和对方一样,就认为两者是重组字符串。比如:

  • A = super
  • B = perus
    如果我们重组 A 字符串中的元素就可以得到 B,反之亦然。

那么,怎么才能用 Elixir 判断字符串是否为重组字符串呢?最简单的方法就是对两个字符串的字符进行排序,然后比较排序好的结果是否相等。

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,首先我们会检查接受的参数是否为 binaries,这是 Elixir 检查参数是否为字符串的方法。 然后,我们会调用把字符串按照字母表排序的函数,这个函数首先把所有字符转换成小写,然后调用 String.graphemes 得到字符串中字素的列表。思路很清晰,对吧?

我们来通过 iex 看一下输出结果:

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

正如上面展示的,最后一次调用 anagrams?返回了 FunctionClauseError,这个错误就是告诉我们模块中没有接受两个非字符串的函数。这正是我们期望的结果:只接受字符串作为参数,其他都不允许。

你可能感兴趣的:(Elixir-字符串)