Elixir Language
Listy
Szukaj…
Składnia
- []
- [1, 2, 3, 4]
- [1, 2] ++ [3, 4] # -> [1,2,3,4]
- hd ([1, 2, 3, 4]) # -> 1
- tl ([1, 2, 3, 4]) # -> [2,3,4]
- [głowa | ogon]
- [1 | [2, 3, 4]] # -> [1,2,3,4]
- [1 | [2 | [3 | [4 | []]]]] -> [1,2,3,4]
- „hello” = [? h,? e,? l,? l,? o]
- keyword_list = [a: 123, b: 456, c: 789]
- keyword_list [: a] # -> 123
Listy słów kluczowych
Listy słów kluczowych to listy, w których każdy element na liście to krotka atomu, po której następuje wartość.
keyword_list = [{:a, 123}, {:b, 456}, {:c, 789}]
Skrótowy zapis do pisania list słów kluczowych jest następujący:
keyword_list = [a: 123, b: 456, c: 789]
Listy słów kluczowych są przydatne do tworzenia uporządkowanych struktur danych pary klucz-wartość, w których dla danego klucza może istnieć wiele elementów.
Pierwszą pozycję na liście słów kluczowych dla danego klucza można uzyskać w następujący sposób:
iex> keyword_list[:b]
456
Przypadkiem użycia list słów kluczowych może być sekwencja nazwanych zadań do uruchomienia:
defmodule TaskRunner do
def run_tasks(tasks) do
# Call a function for each item in the keyword list.
# Use pattern matching on each {:key, value} tuple in the keyword list
Enum.each(tasks, fn
{:delete, x} ->
IO.puts("Deleting record " <> to_string(x) <> "...")
{:add, value} ->
IO.puts("Adding record \"" <> value <> "\"...")
{:update, {x, value}} ->
IO.puts("Setting record " <> to_string(x) <> " to \"" <> value <> "\"...")
end)
end
end
Ten kod można wywołać za pomocą listy słów kluczowych, takiej jak:
iex> tasks = [
...> add: "foo",
...> add: "bar",
...> add: "test",
...> delete: 2,
...> update: {1, "asdf"}
...> ]
iex> TaskRunner.run_tasks(tasks)
Adding record "foo"...
Adding record "bar"...
Adding record "test"...
Deleting record 2...
Setting record 1 to "asdf"...
Listy char
Ciągi znaków w eliksirach to „pliki binarne”. Jednak w kodzie Erlang ciągi są tradycyjnie „listami znaków”, dlatego przy wywoływaniu funkcji Erlang może być konieczne użycie list znaków zamiast zwykłych ciągów Elixir.
Podczas gdy zwykłe ciągi są napisane przy użyciu cudzysłowów "
, listy char są zapisywane za pomocą apostrofów '
:
string = "Hello!"
char_list = 'Hello!'
Listy znaków to po prostu listy liczb całkowitych reprezentujących punkty kodowe każdego znaku.
'hello' = [104, 101, 108, 108, 111]
Ciąg można przekonwertować na listę to_charlist/1
pomocą to_charlist/1
:
iex> to_charlist("hello")
'hello'
I odwrotnie można to zrobić za pomocą to_string/1
:
iex> to_string('hello')
"hello"
Wywołanie funkcji Erlang i konwersja wyniku na zwykły ciąg Elixir:
iex> :os.getenv |> hd |> to_string
"PATH=/usr/local/bin:/usr/bin:/bin"
Wady Komórki
Listy w Elixir są listami połączonymi. Oznacza to, że każdy element na liście składa się z wartości, po której następuje wskaźnik do następnego elementu na liście. Jest to zaimplementowane w Elixir przy użyciu komórek Cons.
Wady komórki to proste struktury danych z „lewą” i „prawą” wartością lub „głową” i „ogonem”.
A |
symbol można dodać przed ostatnim elementem na liście, aby zanotować (niewłaściwą) listę z daną głową i ogonem. Poniżej znajduje się pojedyncza komórka przeciw z 1
jako głową i 2
jako ogonem:
[1 | 2]
Standardowa składnia eliksiru dla listy jest w rzeczywistości odpowiednikiem zapisu łańcucha zagnieżdżonych komórek przeciwnych:
[1, 2, 3, 4] = [1 | [2 | [3 | [4 | []]]]]
Pusta lista []
służy jako ogon komórki przeciw reprezentującej koniec listy.
Wszystkie listy w Elixir są równoważne formie [head | tail]
, gdzie head
jest pierwszą pozycją na liście, a tail
jest resztą listy, minus głowa.
iex> [head | tail] = [1, 2, 3, 4]
[1, 2, 3, 4]
iex> head
1
iex> tail
[2, 3, 4]
Korzystanie z [head | tail]
Notacja [head | tail]
jest przydatna do dopasowania wzorca w funkcjach rekurencyjnych:
def sum([]), do: 0
def sum([head | tail]) do
head + sum(tail)
end
Listy mapowania
map
jest funkcją w programowaniu funkcjonalnym, która otrzymała listę i funkcję, zwraca nową listę z funkcją zastosowaną do każdego elementu na tej liście. W Elixir funkcja map/2
znajduje się w module Enum .
iex> Enum.map([1, 2, 3, 4], fn(x) -> x + 1 end)
[2, 3, 4, 5]
Korzystanie z alternatywnej składni przechwytywania dla funkcji anonimowych:
iex> Enum.map([1, 2, 3, 4], &(&1 + 1))
[2, 3, 4, 5]
Odwołując się do funkcji ze składnią przechwytywania:
iex> Enum.map([1, 2, 3, 4], &to_string/1)
["1", "2", "3", "4"]
Operacje na listach łańcuchowych za pomocą operatora potoku:
iex> [1, 2, 3, 4]
...> |> Enum.map(&to_string/1)
...> |> Enum.map(&("Chapter " <> &1))
["Chapter 1", "Chapter 2", "Chapter 3", "Chapter 4"]
Zrozumienie listy
Eliksir nie ma pętli. Zamiast nich dla list są świetne moduły Enum
i List
, ale są też Listy Rozumienia.
Zrozumienie listy może być przydatne do:
- tworzyć nowe listy
iex(1)> for value <- [1, 2, 3], do: value + 1
[2, 3, 4]
- filtrowanie list, używając
guard
wyrażeń, ale ich używać bezwhen
słowa kluczowego.
iex(2)> odd? = fn x -> rem(x, 2) == 1 end
iex(3)> for value <- [1, 2, 3], odd?.(value), do: value
[1, 3]
- tworzenie własnych map, używając
into
słowa kluczowego:
iex(4)> for value <- [1, 2, 3], into: %{}, do: {value, value + 1}
%{1 => 2, 2=>3, 3 => 4}
Połączony przykład
iex(5)> for value <- [1, 2, 3], odd?.(value), into: %{}, do: {value, value * value}
%{1 => 1, 3 => 9}
streszczenie
Zrozumienie listy:
- używa składni
for..do
z dodatkowymi zabezpieczeniami po przecinkach iinto
słowa kluczowego, gdy zwraca inną strukturę niż listy, tj. mapa. - w innych przypadkach zwracają nowe listy
- nie obsługuje akumulatorów
- nie można zatrzymać przetwarzania, gdy spełniony jest określony warunek
- instrukcje
guard
muszą być pierwsze w kolejności pofor
i przeddo
lubinto
symbolach. Kolejność symboli nie ma znaczenia
Zgodnie z tymi ograniczeniami Zrozumienia listy są ograniczone tylko do prostego użycia. W bardziej zaawansowanych przypadkach najlepszym rozwiązaniem byłoby użycie funkcji z modułów Enum
i List
.
Lista różnic
iex> [1, 2, 3] -- [1, 3]
[2]
--
usuwa pierwsze wystąpienie elementu z lewej listy dla każdego elementu z prawej.
Lista członków
Użyj in
operatorze, aby sprawdzić, czy element jest członkiem listy.
iex> 2 in [1, 2, 3]
true
iex> "bob" in [1, 2, 3]
false
Konwertowanie list na mapę
Użyj Enum.chunk/2
aby pogrupować elementy w listy podrzędne, a Map.new/2
aby przekształcić je w mapę:
[1, 2, 3, 4, 5, 6]
|> Enum.chunk(2)
|> Map.new(fn [k, v] -> {k, v} end)
Dałby:
%{1 => 2, 3 => 4, 5 => 6}