Fork me on GitHub

Колекции

Some contents of this translation may be outdated.
Several major changes were applied to the original lesson since the last update.

Списъци, tuples, ключови думи, асоциативни списъци и функционални комбинатори.

Съдържание

Списъци

Списъците са прости колекции от стойности, могат да се състоят от множество типове; списъците може да съдържат еднакви стойности:

iex> [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]

Elixir имплементира списъка като свързан списък. Това означава, че дължината на списъка е операция от реда O(n). Поради тази причина по-принцип е по-бързо да се добавя в началото отколкото в края на списък:

iex> list = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex> ["π"] ++ list
["π", 3.14, :pie, "Apple"]
iex> list ++ ["Cherry"]
[3.14, :pie, "Apple", "Cherry"]

Конкатенация на списъци

За конкатенацията на списъци се използва оператора ++/2:

iex> [1, 2] ++ [3, 4, 1]
[1, 2, 3, 4, 1]

Бележка относно формата името (++/2) използван отгоре: В Elixir(и Erlang върху, който Elixir е създаден), името на функция или оператор има два компонента: даденото й име(в този случай ++) и нейното arity. Arity е основна част, когато се говори за Elixir (и Erlang) код. Това е броя на аргументите, дадена функция приема(в този случай две). Arity и името са комбинирани с наклонена черта. Ще говорим за това повече по-късно; Това ще ви помогне да разберете нотацията за сега.

Разлика на списъци

Поддръжката за субстракция е осигурено чрез оператора --/2; безопасно е да се извади липсваща стойност:

iex> ["foo", :bar, 42] -- [42, "bar"]
["foo", :bar]

Внимавайте с повтарящи се стойности. Първата поява на всеки елемент от дясно, се премахва от ляво:

iex> [1,2,2,3,2,3] -- [1,2,3,2]
[2, 3]

Забележка: Използва се стриктно сравнение при сравнението на стойности.

Глава / Опашка

Когато използваме списъци е обичайно да работим с главата и опашката на списъка. Главата е първият елемент на списъка, а опашката останалите елементи. Elixir предоставя два полезни метода, hd и tl, за работа с тези части:

iex> hd [3.14, :pie, "Apple"]
3.14
iex> tl [3.14, :pie, "Apple"]
[:pie, "Apple"]

В допълнение към гореспоменатите функции, може да ползвате pattern matching и оператора | за да разделите списъка на глава и опашка; ще разгледаме този подход в дълбочина в следващи уроци:

iex> [head | tail] = [3.14, :pie, "Apple"]
[3.14, :pie, "Apple"]
iex> head
3.14
iex> tail
[:pie, "Apple"]

Tuples

Tuples са подобни на списъци, но се съхраняват последователно в паметта. Поради това достъпваме тяхната дължина бързо, но модификациите са скъпи; новият tuple трябва да бъде изцяло копиран наново в паметта. Tuples се дефинират с къдрави скоби:

iex> {3.14, :pie, "Apple"}
{3.14, :pie, "Apple"}

Обичайно за tuples е да бъдат използвани като механизъм за връщане на допълнителна информация от функции; полезността от това ще стане по-ясна след като навлезем в pattern matching:

iex> File.read("path/to/existing/file")
{:ok, "... contents ..."}
iex> File.read("path/to/unknown/file")
{:error, :enoent}

Списъци с ключови думи

Ключовите думи и асоциативните списъци са асоциативните колекции на Elixir. В Elixir, списък от ключови думи е специален списък от tuples, чиито първи елемент е атом; те имат производителността на списък:

iex> [foo: "bar", hello: "world"]
[foo: "bar", hello: "world"]
iex> [{:foo, "bar"}, {:hello, "world"}]
[foo: "bar", hello: "world"]

Трите характеристики на списъци с ключови думи подчертават тяхната важност:

Поради тези причини списъците с ключови думи най-често се ползват за предаване на опции към функции.

Асоциативни списъци

В Elixir асоциативните списъци съхраняват стойности тип ключ-стойност, за разлика от списъците с ключови думи, те позволяват ключове от всякакъв тип и не са подредени. Може да дефинирате асоциативен списък с%{}:

iex> map = %{:foo => "bar", "hello" => :world}
%{:foo => "bar", "hello" => :world}
iex> map[:foo]
"bar"
iex> map["hello"]
:world

Считано от Elixir 1.2 може да се използват като ключове в асоциативния списък:

iex> key = "hello"
"hello"
iex> %{key => "world"}
%{"hello" => "world"}

Ако дубликат е добавен към асоциативен списък, той ще замени предходната стойност:

iex> %{:foo => "bar", :foo => "hello world"}
%{foo: "hello world"}

Както може да видим от резултата по-горе, съществува специален синтаксис за асоциативни списъци, които съдържат само атоми като ключове:

iex> %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}

iex> %{foo: "bar", hello: "world"} == %{:foo => "bar", :hello => "world"}
true

Друго интересно свойство на асоциативните списъци, е техния синтаксис за обновяване и достъпване на атом ключове:

iex> map = %{foo: "bar", hello: "world"}
%{foo: "bar", hello: "world"}
iex> %{map | foo: "baz"}
%{foo: "baz", hello: "world"}
iex> map.hello
"world"


Споделете тази страница