Elixir: Отображение
Так как язык Эликсир является функциональным языком программирования, то в большинстве случаев списки обрабатываются 'классической' тройкой функций map
, filter
, reduce
. Рассмотрим первую функцию map
, которая переводится как 'отображение', что полностью отражает суть выполняемой операции:
numbers = [1, 2, 3, 4]
doubled_numbers = Enum.map(numbers, fn (x) -> x * 2 end)
IO.puts(doubled_numbers) # => [2, 4, 6, 8]
users = [%{name: "Igor"}, %{name: "John"}, %{name: "Alice"}, %{name: "Isabella"}]
names = Enum.map(users, &(&1[:name]))
IO.puts(names) # => ["Igor", "John", "Alice", "Isabella"]
# либо с помощью паттерн-матчинга
names = Enum.map(users, fn %{name: name} -> name end)
IO.puts(names) # => ["Igor", "John", "Alice", "Isabella"]
Важно понимать, что при обработке переданного в функцию map
списка, создается новый список, а не мутируется исходный, так как язык является иммутабельным. Внутри переданной функции над элементом списка могут выполняться какие-угодно вычисления, однако итоговый список всегда будет такого же размера, как и исходный:
numbers = [1, 2, 3]
incremented_numbers = Enum.map(numbers, fn (x) -> x + 1 end)
IO.puts(numbers) # => [1, 2, 3]
IO.puts(incremented_numbers) # => [2, 3, 4]
stringified = Enum.map(numbers, fn (x) -> "Number: #{x}" end)
IO.puts(stringified) # => ["Number: 1", "Number: 2", "Number: 3"]
Так как функция map
ожидает первым аргументом список, то мы можем с помощью оператора |>
комбинировать несколько преобразований подряд:
numbers = [1, 2, 3, 4]
result =
numbers
|> Enum.map(fn (x) -> x + 1 end)
|> Enum.map(fn (x) -> x * 5 end)
|> Enum.map(fn (x) -> x / 2 end)
|> Enum.map(&Float.round/1)
IO.puts(result) # => [5.0, 8.0, 10.0, 13.0]
Задание
Реализуйте функцию zip
, которая группирует элементы переданных векторов в подвектора. Если вектора отличаются длиной, то вместо сгрупированного элемента оставьте nil
. Для обращения к элементу списка по индексу используйте Enum.at
.
Примеры:
Solution.zip([], [])
# => []
Solution.zip([1, 2, 3, 4], [5, 6, 7, 8])
# => [[1, 5], [2, 6], [3, 7], [4, 8]]
Solution.zip([1, 2], [3, 4])
# => [[1, 3], [2, 4]]
Solution.zip([1, 2], [3])
# => [[1, 3], [2, nil]]
Solution.zip([1], [3, 4])
# => [[1, 3], [nil, 4]]
Упражнение не проходит проверку — что делать? 😶
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя 🤔
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно 🙄
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.