2015-07-21 1 views
18

Ho un elenco di parole chiave degli errori Ecto changeset Vorrei convertirmi in una mappa in modo che il parser JSON Poison possa pubblicare correttamente un elenco di errori di convalida nel formato JSON.Elixir: come convertire un elenco di parole chiave in una mappa?

in modo da ottenere un elenco di errori nel modo seguente:

[:topic_id, "can't be blank", :created_by, "can't be blank"] 

... e mi piacerebbe ottenere una mappa degli errori in questo modo:

%{topic_id: "can't be blank", created_by: "can't be blank"} 

In alternativa, se potessi convertirlo in una lista di stringhe, potrei usare anche quello.

Il modo migliore per eseguire una di queste attività?

risposta

34

Quello che hai non è un elenco di parole chiave, è solo un elenco con ogni elemento dispari che rappresenta una chiave e ogni elemento pari che rappresenta un valore.

La differenza è:

[:topic_id, "can't be blank", :created_by, "can't be blank"] # List 
[topic_id: "can't be blank", created_by: "can't be blank"] # Keyword List 

Un elenco di parole chiave può essere trasformato in una mappa utilizzando Enum.into/2

Enum.into([topic_id: "can't be blank", created_by: "can't be blank"], %{}) 

Dal momento che la struttura dei dati è una lista, è possibile convertire utilizzando Enum.chunk/2 e Enum.reduce/3

[:topic_id, "can't be blank", :created_by, "can't be blank"] 
|> Enum.chunk(2) 
|> Enum.reduce(%{}, fn ([key, val], acc) -> Map.put(acc, key, val) end) 

È possibile Maggiori informazioni sugli elenchi di parole chiave su http://elixir-lang.org/getting-started/maps-and-dicts.html

+2

non posso provarlo in questo momento, ma ho la sensazione che si dovrebbe essere in grado di ridurre l'ultimo esempio di '[...] | > Enum.chunk (2) |> Enum.into (% {}) ' –

+0

Ah, ho perso la differenza tra un elenco e un elenco di parole chiave. Grazie! –

+0

Anche io sto avendo lo stesso problema di OP, solo credo che Modifiche abbia cambiato la sua implementazione. ATOW gli errori del changeset _è_ un elenco di parole chiave, ad es. '[campo_1: {" non valido ", [tipo: Ecto.UUID]}, campo_2: {" non può essere vuoto ", []}]'. Sono stato in grado di convertire in una mappa usando l'approccio 'Enum.into' di questa risposta con' error_map = Enum.into (changeset.errors,% {}) '. Come mappa, potrei quindi ottenere il mio messaggio con '{err_msg, _type} = Map.fetch! (Error_map,: field_1)'. – ibgib

7

Un altro modo per farlo è combinare Enum.chunk/2 con Enum.into/3. Per esempio:

[:topic_id, "can't be blank", :created_by, "can't be blank"] 
|> Enum.chunk(2) 
|> Enum.into(%{}, fn [key, val] -> {key, val} end) 
5

Ancora un altro modo per farlo è quello di utilizzare delle lista di comprensione:

iex> list = [:topic_id, "can't be blank", :created_by, "can't be blank"] 
iex> map = for [key, val] <- Enum.chunk(list, 2), into: %{}, do: {key, val} 
%{created_by: "can't be blank", topic_id: "can't be blank"} 

Inoltre è possibile convertire la vostra lista di parole chiave lista:

iex> klist = for [key, val] <- Enum.chunk(list, 2), do: {key, val} 
[topic_id: "can't be blank", created_by: "can't be blank"] 

potrebbe essere utile anche in alcuni casi.

Si può leggere di più su questo caso l'uso in http://elixir-lang.org/getting-started/comprehensions.html#results-other-than-lists