Read data from a text file and generate a map

Hi all, I have a .txt file with information like this
11111 0
11112 1
11113 2
11114 3
11115 4
11116 5
11121 6
11122 7

66664 zzgl
66665 zzz
66666 zzzz

What I have to do:

  1. read the file
  2. return a map like this
    %{
    “11111” => “0”
    “11112” => “1”
    “11113” => “2”

    “66664” => “zzgl”
    “66665” => “zzz”
    “66666” => “zzzz”
    }

Here’s what I have tried

def get_map(file_name) do
      {:ok, file} = File.read(file_name)
      # create a new map
      result_map = %{}

     # create a map with key = first word of the line and value = second word of the line
      file
      |> String.split("\n")
      |> Enum.map(fn line -> String.split(line, " ") end)
      |> Enum.reduce(result_map, fn [key, value], acc -> Map.put(acc, key, value) end)
    end

I got something returned but with errors.

** (FunctionClauseError) no function clause matching in anonymous fn/2 in DiceWare.get_map/1    
    The following arguments were given to anonymous fn/2 in DiceWare.get_map/1:
    
        # 1
        [""]
    
        # 2
        %{
          "42464" => "manila",
          "45512" => "osmose",
          "63122" => "unicri",
          "31645" => "heimat",
          "52552" => "riegel",
          "41251" => "leimt",
          "55144" => "sierra",
          "11223" => "44",
          "16131" => "bruch",
          "35413" => "kniend",
          "41211" => "lehmig",
          "45154" => "oase",
          "31261" => "habe",
          "32216" => "hetzte",
          "51641" => "rang",
          "64456" => "wenden",
          "26435" => "gitter",
          "36232" => "krung",
          "35163" => "kkkk",
          "55213" => "sinus",
          "21533" => "donau",
          "63116" => "uni",
          "53222" => "rosten",
          "23533" => "fakten",
          "12323" => "abu",
          "34462" => "kauer",
          "13412" => "anzug",
          "23241" => "ernte",
          "61324" => "teilt",
          "63653" => "vwx",
          "44422" => "neogen",
          "66312" => "zhd",
          "45354" => "onyx",
          "11416" => "500",
          "64212" => "wamme",
          "53351" => "ruhm",
          "52316" => "regime",
          "63421" => "verl",
          "25266" => "fuerst",
          "24311" => "fichte",
          "24432" => "fj",
          "23654" => "faulig",
          "12646" => "alias",
          "14333" => "baryon",
          "21655" => "dronte",
          "36513" => "lagern",
          "11662" => "$",
          "42343" => "magnat",
          "53424" => "russig",
          "55555" => "spleen",
          ...
        }
    
    (elixirexercise01 0.1.0) lib/diceware.ex:24: anonymous fn/2 in DiceWare.get_map/1
    (elixir 1.14.1) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
        }

I don’t really understand what I’ve done wrong, why does the map start from the middle of the file?
what do I have to change to make it work?

There’s probably a newline at the end of the file that you didn’t account for.

Try String.trim() before String.split("\n"), or do String.split("\n", trim: true).

P.S. Posting this during Advent of Code is fortunate timing :grin:

2 Likes

I’d do something like this. You might have to Stream.reject empty lines or so…

file_name
|> File.stream!()
|> Stream.map(&String.split/1)
|> Stream.map(&List.to_tuple/1)
|> Enum.into(%{})
3 Likes

String.split("\n", trim: true) works like a charm! thank youu!

file_name
|> File.stream!()
|> Stream.map(&String.split/1)
|> Stream.map(&List.to_tuple/1)
|> Enum.into(%{})

This one works too!