user177800
user177800

Reputation:

Convert nested Lists into a List of Tuples

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.

Upvotes: 2

Views: 1432

Answers (4)

Hynek -Pichi- Vychodil
Hynek -Pichi- Vychodil

Reputation: 26121

Even shorter:

KVL = [{list_to_atom(K), V} || [K,V] <- [string:tokens(T,"=") || T <- L]].

Upvotes: 1

Christian
Christian

Reputation: 9486

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?

Upvotes: 2

Zed
Zed

Reputation: 57648

KVL = [begin [K,V]=string:tokens(T,"="), {list_to_atom(K), V} end || T <- L]. 

;)

Upvotes: 4

user177800
user177800

Reputation:

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"}]

Upvotes: 1

Related Questions