2009-11-30 177 views
2

的名單上有以下列表轉換嵌套列表到元組

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

我想創建一個快譯通,其中=左側是關鍵,右邊是值。 最好是鑰匙是原子的地方。

使用下面的列表理解我得到這個。

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

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

什麼,我現在努力的是如何嵌套列表轉換成元組,所以我可以將它們發送到元組 的名單,我可以將它們發送到字典:from_list

我想要的是像這樣

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

我知道必須有這樣做一個簡潔的方式,但我不能讓我的頭周圍。

回答

1

更短:

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

你也可以省略逗號後的幾個空格等...... – Zed 2009-12-02 20:25:01

+1

當提高可讀性時,我喜歡空格;-) – 2009-12-03 09:21:28

1

我終於明白了!

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

;)

+0

.... + 1:漂亮的Zed! – jldupont 2009-12-01 00:56:36

+0

如果是外部輸入數據,請記得使用'list_to_existing_atom/1'(請參閱Christian的回答)。 – 2009-12-01 09:42:19

+0

@Adam,Christian:如果你沒有在嵌入模式下運行,你有可能在構建第一個字典時,處理字典的模塊甚至沒有加載。因此,期望的「關鍵」原子也不加載,即它們不存在於原子表中。猜猜list_to_existing_atom會產生什麼結果... 所以,至少當你覺得需要傳遞這個list_to_existing_atom thingie時,至少應該總是堅持「確保原子已經存在」。 – Zed 2009-12-01 10:47:35

2

小免責聲明從這個問題的任何人採取的提示。使用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)]. 

的原因是,它是一個可能的DoS攻擊,如果(惡意)用戶提供的數據可以創建萬元和數百萬種獨特的原子。獨特的原子表是1600萬個左右的原子。

此外,令牌在字符串中拆分每個等號。是不是更好地分裂只有第一個?

+0

在我的輸入數據中只會有一個=每個字符串 – 2009-12-01 01:50:28