tags:

views:

148

answers:

4

I have the following list

["txtvers=1","userid=3A6524D4-E31C-491D-94DD-555883B1600A","name=Jarrod Roberson","version=2"]

I want to create a Dict where the left side of the = is the key and the right side is the value. Preferably where the key is an atom.

Using the following list comprehension I get this.

 KVL = [string:tokens(T,"=") || T <- TXT].

[["txtvers","1"], ["userid","3A6524D4-E31C-491D-94DD-555883B1600A"], ["name","Jarrod Roberson"], ["version","2"]]

what I am struggling with now is how to convert the nested lists into tuples so I can send them into a list of tuples where I can send them into dict:from_list

what I want is something like this

[{txtvers,"1"}, {userid,"3A6524D4-E31C-491D-94DD-555883B1600A"}, {name,"Jarrod Roberson"}, {version,"2"}]

I know there has to be a concise way to do this but I just can't get my head around it.

+1  A: 

I actually got it to work finally!

A = [ string:tokens(KV,"=") || KV <- TXT].
[["txtvers","1"],
 ["userid","3A6524D4-E31C-491D-94DD-555883B1600A"],
 ["name","Jarrod Roberson"],
 ["version","2"]]
B = [{list_to_atom(K),V} || [K|[V|_]] <- A].
[{txtvers,"1"},
 {userid,"3A6524D4-E31C-491D-94DD-555883B1600A"},
 {name,"Jarrod Roberson"},
 {version,"2"}]
fuzzy lollipop
+4  A: 
KVL = [begin [K,V]=string:tokens(T,"="), {list_to_atom(K), V} end || T <- L].

;)

Zed
....+1: nice Zed!
jldupont
And remember to use `list_to_existing_atom/1` if it is external input data (see Christian's answer).
Adam Lindberg
@Adam, Christian: if you are not running in embedded mode, you have a chance that at the time of building the first dict, the module that will handle the dict is not even loaded. Thus, the expected "key" atoms are not loaded either, i.e. they do not exist in the atom table. Guess what will be the result of list_to_existing_atom ...So please at least always stick a "make sure the atoms are already present" whenever you feel the need to communicate this list_to_existing_atom thingie.
Zed
+2  A: 

A little disclaimer on anyone else taking hints from this question. It is always a good idea to turn lists into atoms using list_to_existing_atom.

split_keyvalue(Str) ->
  try 
    {K, [$=|V]} = lists:splitwith(fun(X) -> X =/= $= end, Str),
    {erlang:list_to_existing_atom(K), V} 
  catch 
     error:badarg -> 
       fail 
  end.

split_keyvalues(List) ->
  [KV || {_,_}=KV <- lists:map(fun split_keyvalue/1, List)].

The reason is that it is a possible DoS attack if (malicious) user supplied data can create million and millions of unique atoms. The table of unique atoms is max 16 million atoms big or so.

Also, tokens splits every equal sign in the string. Isnt it better to split on the first one only?

Christian
in my input data there will only ever be one = per string
fuzzy lollipop
A: 

Even shorter:

KVL = [{list_to_atom(K), V} || [K,V] <- [string:tokens(T,"=") || T <- L]].
Hynek -Pichi- Vychodil
You can also leave out a few spaces after commas, etc...
Zed
I like spaces when improve readability ;-)
Hynek -Pichi- Vychodil