плохо это делаю
Можете подсказать как получше подойти к написанию такого простенького кода?
В целом у меня главная проблема с этим громадным выражением которое преобразует список строк во вложенные списки с числами
["123\r\n1223123\r\n999\r\n", "555\r\n696\r\n" ] ->
[[123, 1223123, 999], [555, 696]]
def mostCalories do
{:ok, data} = File.read("./input.txt")
listData = String.split(data, "\r\n\r\n")
numList =
listData
|> Enum.map(fn elve ->
String.split(elve, "\r\n")
|> Enum.map(fn str ->
case Integer.parse(str) do
{int, _rest} -> int
:error -> 0
end
end)
end)
summedList = numList |> Enum.map(&Enum.sum(&1))
sortedList = Enum.sort(summedList, &>=/2)
Enum.take(sortedList, 3) |> Enum.sum()
end
если я правильно понял что код пытается сделать, то не так уж плохо, только причесать надо. что то вроде этого (не запускал самой собой) def most_calories do {:ok, data} = File.read("./input.txt) data |> String.split("\r\n\r\n") |> Enum.map(fn line -> line |> String.split("\r\n") |> Enum.map(fn str -> case Integer.parse(str) do {int, _rest} -> int :error -> 0 end end) |> Enum.sum() end) |> Enum.sort(:desc) |> Enum.take(3) |> Enum.sum() end
Просто выносишь в отдельную функцию и не будет этого громадного выражения
Если я не вижу функцию, значит её нет)
чаще всего fn -> ... лучше вынести в отдельную именованую функцию defp .... А лесенку из двух вложенных fn и подавно, иначе при чтении такого кода можно случайно сломать мозг)
и потом скроль туда сюда ищи чтобы понять что происходит)
Если давать осмысленные названия, то и так понятно
реальн что это я, нейминг функций это же давно решенная проблема, все это знают
Если уж занудствовать, то считается хорошим тоном объявлять функцию там где она применяется (если это лямбда функция). Если же она переиспользуется в нескольких местах - стоит вынести в приватную функцию модуля
defmodule CalParser do @spec decode(binary()) :: list(list(integer())) def decode(raw_data) do raw_data |> split_chunks() |> Enum.map(&parse_chunk/1) end defp split_chunks(data), do: String.split(data, "\r\n\r\n") defp parse_chunk(chunk) do chunk |> String.split("\r\n") |> Enum.map(&parse_line/1) end defp parse_line(line) do case Integer.parse(line) do {int, _rest} -> int :error -> 0 end end end def most_calories() do data = "input.txt" |> File.read!() |> CalParser.decode() summed_data = Enum.map(data, &Enum.sum/1) sorted_data = Enum.sort(summed_data, &>=/2) top_three_sum = sorted_data |> Enum.take(3) |> Enum.sum() end Если нету надобности в summed и sorted то тогда надо в один пайп. Просто не понятно что именно ты хочешь выводить
как бы да, но как бы нет
Я лично стараюсь не писать функции с глубиной больше двух пайпов. Поэтому я бы писал примерно так: def mostCalories do {:ok, data} = File.read("./input.txt") num_list = data |> String.split(data, "\r\n\r\n") |> Enum.map(fn elve -> elve |> String.split("\r\n") |> Enum.map(&to_int/1) end) # ... end def to_int(str) when is_bitstring(str) do case Integer.parse(str) do {int, _rest} -> int :error -> 0 end end
Обсуждают сегодня