Powered by AppSignal & Oban Pro

parsing explorations

livebooks/parsing_explorations.livemd

parsing explorations

Parse Line

defmodule Y do
  def parse_row(line) do
    parse_row(line, line, 0)
  end

  def parse_row(line, <<?;, _rest::binary>>, count) do
    <<city::binary-size(count), ?;, temp_value::binary>> = line
    {city, parse_temperature(temp_value)}
  end

  def parse_row(line, <<_current_char, rest::binary>>, count) do
    parse_row(line, rest, count + 1)
  end

  def parse_temperature(<<?-, d1, ?., d2, _::binary>>) do
    -(char_to_num(d1) * 10 + char_to_num(d2))
  end

  def parse_temperature(<<d1, ?., d2, _::binary>>) do
    char_to_num(d1) * 10 + char_to_num(d2)
  end

  def parse_temperature(<<?-, d1, d2, ?., d3, _::binary>>) do
    -(char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3))
  end

  def parse_temperature(<<d1, d2, ?., d3, _::binary>>) do
    char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3)
  end

  defp char_to_num(char), do: char - ?0
end

x = "Mumbai;7.2"

Y.parse_row(x)
# <<b>> = "4"

# b - ?0

<<city::binary-size(6), ?;, temp::binary>> = "Mumbai;7.2"

{city, temp}

Parse multiple lines

data = "Sacramento;16.2\nMakurdi;27.9\nTromsø;3.2"
defmodule Z do
  def parse_rows(input) do
    parse_rows(input, [])
  end

  def parse_rows("", acc), do: acc

  def parse_rows(input, acc) do
    {city, temp, rest} = parse_row(input)
    parse_rows(rest, [{city, temp} | acc])
  end

  def parse_row(line) do
    parse_row(line, line, 0)
  end

  def parse_row(line, <<?;, _rest::binary>>, count) do
    <<city::binary-size(count), ?;, temp_value::binary>> = line
    {temp, remaining} = parse_temperature(temp_value)
    {city, temp, remaining}
  end

  def parse_row(line, <<_current_char, rest::binary>>, count) do
    parse_row(line, rest, count + 1)
  end

  def parse_temperature(<<?-, d1, ?., d2, ?\n, rest::binary>>) do
    {-(char_to_num(d1) * 10 + char_to_num(d2)), rest}
  end

  def parse_temperature(<<?-, d1, ?., d2, rest::binary>>) do
    {-(char_to_num(d1) * 10 + char_to_num(d2)), rest}
  end

  def parse_temperature(<<d1, ?., d2, ?\n, rest::binary>>) do
    {char_to_num(d1) * 10 + char_to_num(d2), rest}
  end

  def parse_temperature(<<d1, ?., d2, rest::binary>>) do
    {char_to_num(d1) * 10 + char_to_num(d2), rest}
  end

  def parse_temperature(<<?-, d1, d2, ?., d3, ?\n, rest::binary>>) do
    {-(char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3)), rest}
  end

  def parse_temperature(<<?-, d1, d2, ?., d3, rest::binary>>) do
    {-(char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3)), rest}
  end

  def parse_temperature(<<d1, d2, ?., d3, ?\n, rest::binary>>) do
    {char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3), rest}
  end

  def parse_temperature(<<d1, d2, ?., d3, rest::binary>>) do
    {char_to_num(d1) * 100 + char_to_num(d2) * 10 + char_to_num(d3), rest}
  end

  defp char_to_num(char), do: char - ?0
end

result = Z.parse_rows(data)

ets table types

ets_table = :ets.new(:station_stats, [:duplicate_bag, :public])

:ets.insert(ets_table, {"", %{x: 1}})
:ets.insert(ets_table, {"", %{x: 1}})
:ets.tab2list(ets_table)
[1, 2, 3, ""] |> Enum.filter(fn x -> x == "" end)