Когда я использую команду
ListFilter.call(["1", "3", "6", "43","6"])
код возвращается
{:ok, 3}
но когда я включаю "abc" и "банан"
ListFilter.call(["1", "2", "3", "43", "abc", "banana", "6"])
код возвращает ошибку.
Можете ли вы помочь мне написать этот код, чтобы вернуть 3, когда я буду использовать «abc» и «банан» вместе с другими строками с числами?
Вот мой текущий код:
defmodule ListFilter do
def call(list) do
{
:ok,
list
|> Enum.map(&String.to_integer/1)
|> Enum.filter(&(rem(&1, 2) == 1))
|> Enum.count()
}
end
def call() do
{:error, "Its wrong!"}
end
end
Вы не спрашивали, но на вашем месте я бы создал небольшой дефп, чтобы изолировать этот тест на нечетность числа. Прямо сейчас у вас есть: Enum.filter(&(rem(&1, 2) == 1))
и это нормально. Но если бы вы сделали что-то вроде этого: defp is_odd?(n), do: rem(n,2) == 1
А потом сделали Enum.filter(is_odd?(&1))
Думаю, ваш замысел был бы более понятен другим разработчикам (и, возможно, вам самим, если вам нужно поддерживать код через несколько месяцев).
String.to_integer
вызывает ошибку, когда строку нельзя преобразовать в целое число. Вместо этого попробуйте Integer.parse
или просто отклоните те строки, которые не содержат только цифры.
def call(list) do
{
:ok,
list
|> Enum.reject(&(&1 !~ ~r/^\-?\d+$/)) # reject the strings that can't be converted to integers
|> Enum.map(&String.to_integer/1)
|> Enum.filter(&(rem(&1, 2) == 1))
|> Enum.count()
}
end
Привет, Эфир! Большое спасибо за ваш ответ! Когда я использую эту часть кода |> Enum.reject(&(&1 !~ ~r/^\-?\d+$/)) Он отклоняет все строки, которые у меня есть в моем списке =/. Когда я использую только код, он возвращает {:ok, []} Когда я использую полный код, он возвращает {:ok, 0}. Вы можете помочь мне решить эту проблему? Спасибо =).
Как упоминал Этерус, Integer.parse/1 — лучший выбор, потому что он позволяет определить, успешно ли проанализирована строка. Вы можете сделать это за один проход, используя Enum.count/2 вот так:
Enum.count(list, &match?({int, ""} when rem(int, 2) == 1, Integer.parse(&1)))
count/2
.Integer.parse(&1)
пытается разобрать элемент.{int, ""}
, это целое число. Если это также соответствует условию защиты when rem(int, 2) == 1
, это странно.
Если вы делаете это вручную, используя
def
для пользовательского определения своей функции, вы можете добавить блокtry
иexcept
, чтобы избежать случаев, повторяя, где, еслиint(list[index])
вернет ошибку, потому что элемент является строкой, он просто проигнорирует этот случай.