0
votes

I have a list of addresses and I need to fix the records, some of the records have the house number as a range and I need to split it into multiple records. How would I enumerate over the list and fix/duplicate the records?

defmodule EnumTesting do

  def list_stuff() do
    list = [ %{street: "street", nr: "2" }, %{street: "street", nr: "4" }, %{street: "street", nr: "6-10" } ]
    list |> Enum.filter(&needs_fixing?(&1))
  end

  defp needs_fixing?(item) do
    String.contains?(item.nr, "-")
  end

end

Expected result:

[ %{street: "street", nr: "2" }, %{street: "street", nr: "4" }, %{street: "street", nr: "6" }, %{street: "street", nr: "8" }, %{street: "street", nr: "10" } ]
2
Why doesn't the expected result have nr 7 and 9?Dogbert
@Dogbert because in many countries street numbers are odd on one side of the street and even on the other one. This side is even :)Aleksei Matiushkin
@mudasobwa well the question seems to be unclear then. What if nr is "8-11" (even-odd)? what if it's "7-10" (odd-even)?Dogbert
I's not that important to me to handle how I split the range I'm just not sure of how to duplicate records and return them in the same list.Bjarki Heiðar

2 Answers

1
votes

You have need_fixing? fine, so all you need to do is implement fixing function.

def fixing_function(%{nr: range, street: street}) do
  [a, b] = range |> String.split("-") |> Enum.map(&String.to_integer/1)
  for value <- Range.new(a, b), do: %{street: street, nr: "#{value}"}
end

This gives you fixed addresses and you add append this list to the list of valid entries.

It returns entries for 6, 7, 8, 9 and 10. To use it only for even or odd number you can apply there simple filter function, use :lists:seq or Stream.iterate.

0
votes
def fix!(%{street: street, nr: nr}) do
  case Regex.scan(~r|\d+|, nr, capture: :all_but_first) do
    [nr] -> [%{street: street, nr: nr}]
    [from, two] -> String.to_integer(from)..String.to_integer(to)
                   |> Enum.map(fn i -> %{street: street, nr: "#{i}"} end)
    _ -> raise "Something went wrong: input is incorrect!"
  end
end

def list_stuff() do
  list = [%{street: "street", nr: "2" }, 
          %{street: "street", nr: "4" },
          %{street: "street", nr: "6-10" } ]
  list |> Enum.flat_map(&fix!/1)
end

The above will return 5 records for the last element, 6 through 10, but as you have stated in comments, you are aware on how to deal with that.