Convert nested Lists into a List of Tuples - erlang

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.

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

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?

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

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

Related

F#: Returning a list with element at index changed

In F# I need to get a list from an existing list with the value at a particular index changed from the original. All I can find on google and here relates to changing something based on value rather than index (fair enough, because lists don't really have a concept of "index", but I bet everyone knew what I meant).
This is obviously easy enough to code. At the moment I have:
// Replace element at index with newElement in seq. Does nothing if index is outside seq.
let updateElement index newElement seq =
let rec updateElementHelper seq count result =
match seq with
| [] -> result |> List.rev
| head::tail ->
if count = index then
updateElementHelper [] (count + 1) (newElement::result)#tail
else
updateElementHelper tail (count + 1) (head::result)
updateElementHelper seq 0 []
which seems to work just fine, but is there a more native way than this?
(F# newbie - or rather, returing after a very long break and never having got all that far the first time around).
The easiest way to implement this is probably to use the List.mapi function - it calls a function you provide for each element of the list and gives you an index, so you can either return the original element or your new element, depending on the index:
let updateElement index element list =
list |> List.mapi (fun i v -> if i = index then element else v)
updateElement 4 40 [ 0 .. 9 ]
As noted by #Jarak, if you need to do this often, then it might be worth thinking whether there is some other more functional approach to your problem where you do not rely on indices - doing something like this would not be very typical thing to do in functional code.
I am assuming that you don't want to allow the list to be mutable. If you did, then you could just index into the list and update the value, e.g. mylist.[index] <- newValue.
I will say right now that any operation on a list that uses any other sort of access than the typical "head + tail -> recurse on tail" style is a strong sign that a list isn't the right data structure for your operation. See e.g. Juliet's answer here. Typically, if you want to be operating on a linear data structure by index, an array is your best bet.
The easiest way I can think of to do this if you still want to do it with a list, would be something like the following:
let newList = oldList.[..index - 1] # (newValue :: oldList.[index + 1..])
(I might possibly have the indices slightly off)
This will probably have very poor performance, however. I think it would be reasonably fair to say that many F#-ers would call any use of # or List slicing a code smell. As a very infrequent operation on small lists it might be alright, but if it will be used frequently, or on large lists, then it would be a good time to start thinking if a list is really the right collection data structure for your task.

Affix a string to items within a lists:flatten in Erlang?

I have a list like this one ['a','b','c','d'] and what I need is to add a affix to each item in that list like : ['a#erlang','b#erlang','c#erlang','d#erlang']
I tried using 1lists:foreach1 and then concat two strings to one and then lists:append to the main list, but that didn't work for me.
Example of what I tried:
LISTa = [],
lists:foreach(fun (Item) ->
LISTa = lists:append([Item,<<"#erlang">>])
end,['a','b','c','d'])
Thanks in advance.
1> L = ['a','b','c','d'].
[a,b,c,d]
2> [ list_to_atom(atom_to_list(X) ++ "#erlang") ||X <- L].
[a#erlang,b#erlang,c#erlang,d#erlang]
Please try this code, you can use list_to_atom and atom_to_list.
This will do the trick (using list comprehensions):
1> L = ["a","b","c","d"].
["a","b","c","d"]
2> R = [X ++ "#erlang" || X <- L].
["a#erlang","b#erlang","c#erlang","d#erlang"]
3>
Notice that I changed the atoms for strings; It's discouraged to "create atoms on the fly/dynamically" in Erlang, so I have that framed in my mind. If you still need so, change the implementation a little bit and you are good to go.
NOTE: I'm assuming the concatenation between atoms and binaries is, somehow, something you did not do on purpose.

Erlang list comprehension, once again

I'm trying to get a list comprehension working, which intention is to verify that each element X in List is followed by X+Incr (or an empty list). Later, I shall use that list and compare it with a list generated with lists:seq(From,To,Incr).
The purpose is to practice writing test cases and finding test properties.
I've done the following steps:
1> List.
[1,3,5,8,9,11,13]
2> Incr.
2
3> List2=[X || X <- List, (tl(List) == []) orelse (hd(tl(List)) == X + Incr)].
[1]
To me, it seem that my list comprehension only takes the first element in List, running that through the filter/guards, and stops, but it should do the same for EACH element in List, right?
I would like line 3 returning a list, looking like: [1,2,9,11,13].
Any ideas of how to modify current comprehension, or change my approach totally?
PS. I'm using eqc-quickcheck, distributed via Quviq's webpage, if that might change how to solve this.
The problem with your list comprehension is that List always refers to the entire list. Thus this condition allows only those X that are equal to the second element of List minus Incr:
(hd(tl(List)) == X + Incr)
The second element is always 3, so this condition only holds for X = 1.
A list comprehension cannot "look ahead" to other list elements, so this should probably be written as a recursive function:
check_incr([], _Incr) ->
true;
check_incr([_], _Incr) ->
true;
check_incr([A, B | Rest], Incr) ->
A + Incr == B andalso check_incr([B | Rest], Incr).
Maybe I'm misunderstanding you, but a list comprehension is supposed to be "creating a list based on existing lists". Here's one way to generate your list using a list comprehension without using lists:seq:
> Start = 1, Inc = 2, N = 6.
6
> [Start + X*Inc || X <- lists:seq(0,N)].
[1,3,5,7,9,11,13]
You could do something like this:
> lists:zipwith(fun (X, Y) -> Y - X end, [0 | List], List ++ [0]).
[1,2,2,2,2,2,2,-13]
Then check that all elements are equal to Incr, except the first that should be equal to From and the last that should be greater or equal than -To.
One quick comment is that the value List does NOT change when in the comprehension is evaluated, it always refers to the initial list. It is X which steps over all the elements in the list. This means that your tests will always refer to the first elements of the list. As a list comprehension gives you element of a list at a time it is generally not a good tool to use when you want to compare elements in the list.
There is no way with a list comprehension to look at successive sublists which is what you would need (like MAPLIST in Common Lisp).

How to provide value and get a Key back

So I have made 2 databases:
Db1 that contains: [{james,london}]
Db2 that contains: [{james,london},{fredrik,berlin},{fred,berlin}]
I have a match function that looks like this:
match(Element, Db) -> proplists:lookup_all(Element, Db).
When I do: match(berlin, Db2) I get: [ ]
What I am trying to get is a way to input the value and get back the keys in this way: [fredrik,fred]
Regarding to documentation proplists:lookup_all works other way:
Returns the list of all entries associated with Key in List.
So, you can lookup only by keys:
(kilter#127.0.0.1)1> Db = [{james,london},{fredrik,berlin},{fred,berlin}].
[{james,london},{fredrik,berlin},{fred,berlin}]
(kilter#127.0.0.1)2> proplists:lookup_all(berlin, Db).
[]
(kilter#127.0.0.1)3> proplists:lookup_all(fredrik, Db).
[{fredrik,berlin}]
You can use lists:filter and lists:map instead:
(kilter#127.0.0.1)7> lists:filter(fun ({K, V}) -> V =:= berlin end, Db).
[{fredrik,berlin},{fred,berlin}]
(kilter#127.0.0.1)8> lists:map(fun ({K,V}) -> K end, lists:filter(fun ({K, V}) -> V =:= berlin end, Db)).
[fredrik,fred]
So, finally
match(Element, Db) -> lists:map(
fun ({K,V}) -> K end,
lists:filter(fun ({K, V}) -> V =:= Element end, Db)
).
proplists:lookup_all/2 takes as a first argument a key; in your example, berlin is a value and it's not a key therefore an empty list is returned.
Naturally, you can use recursion and find all the elements (meaning that you will use it like an ordinary list and not a proplist).
Another solution is to change the encoding scheme:
[{london,james},{berlin,fredrik},{berlin,fred}]
and then use proplists:lookup_all/2
The correct way to encode it depends on the way you will access the data (what kind of "queries" you will perform most); but unless you manipulate large amounts of data (in which case you might want to use some other datastructure) it isn't really worth analyzing.

How to create a list of 1000 random numbers in Erlang?

I'm sure that there is a function for that. I just want to make a list of 1000 numbers, each one of them which should be random.
To generate a 1000-element list with random numbers between 1 and 10:
[rand:uniform(10) || _ <- lists:seq(1, 1000)].
Change 10 and 1000 to appropriate numbers. If you omit the 10 from from the rand:uniform call, you'll get a random floating point number between 0.0 and 1.0.
On Erlang versions below 18.0: Use the random module instead. Caution! You need to run random:seed/3 before using it per process, to avoid getting the same pseudo random numbers.
Make sure to seed appropriately.
> F = fun() -> io:format("~p~n", [[random:uniform(10) || _ <- lists:seq(1, 10)]]) end.
> spawn(F).
[1,5,8,10,6,4,6,10,7,5]
> spawn(F).
[1,5,8,10,6,4,6,10,7,5]
Your intuition is that the results would be different. A random seed in Erlang is process specific. The default seed is fixed though. That's why you get the same result even though there are two processes in the example.
> G = fun() -> {A1,A2,A3} = now(),
random:seed(A1, A2, A3),
io:format("~p~n", [[random:uniform(10) || _ <- lists:seq(1, 10)]])
end.
> spawn(G).
[3,1,10,7,9,4,9,2,8,3]
> spawn(G).
[9,1,4,7,8,8,8,3,5,6]
Note that if the return value of now() is the same in two different processes you end up with the same problem as above. Which is why some people like to use a gen_server for wrapping random number generation. Alternatively you can use better seeds.
i will be more then happy to get also a site that i will be able to
read it there. thanks.
You should check out Learn You Some Erlang which will guide you through the language.
Pseudorandom number generator from crypto module works better crypto:rand_uniform(From, To).
To generate a 1000-element list with random numbers between 1 and 10:
crypto:start(),
[crypto:rand_uniform(1, 10) || _ <- lists:seq(1, 1000)].
From Erlang Central wiki:
http://erlangcentral.org/wiki/index.php?title=Random_Numbers
Where N = no of items, StartVal = minimum value and Lim = maximum value
generate_random_int_list(N,StartVal,Lim) ->
lists:map(fun (_) -> random:uniform(Lim-StartVal) + StartVal end, lists:seq(1,N)).
You need to correctly seed first of all.
_ = rand:seed(exs1024s),
[rand:uniform(100) || _ <- lists:seq(1, 1000)].

Resources