Erlang map nested list - list

I have i list:
[["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]].
How can i applicate function F to each element of this list? How can i map this list?
Thank you.

If assuming by element you mean "asd", your main List will always be two levels deep as in your example and your returned result shall be in the same format, this will due.
List1 = [["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]]
[ [ F(String) || String <- List2 ] || List2 <- List1 ]
If you mean that your element is ["asd","ddsa"] just use lists:map/2 or list comprehension as below.
List1 = [["asd", "ddsa"], ["ASD", "ASD"], ["FH", "SDFDF]]
[ F(List2) || List2 <- List1 ]

You could define a deepMap function, performing something like:
deepMap(Fun, T) ->
case is_list(T) of
true -> lists:map(fun(E) -> deepMap(Fun,E) end, T);
false -> Fun(T)
end.
If the input is not a list, evaluate your function. If it is a list, apply deepMap to all elements using map, using your function.

Related

f# iterate and use List<List<string>>

I have simple list that contains inside list
let ftss = [
["a","aData"],["b","bData"]
]
I want to iterate and access the elements "a" and "aData" etc.
I tried
List.iter (fun item ->
for i in 0..1 do
printfn "%s" item[i])
how do i access the elements inside the internal list?
Thanks
So, 1st thing is a comma isnt a delimter in a list, but in a tuple ',' so
let ftss = [
["a","aData"],["b","bData"]
]
is actually of type
val ftss: ((string * string) list * (string * string) list) list =
i.e. its a list of 1 entry of a tuple of a list of 1 entry each of a tuple.
which I THINK isnt what you intended?
I THINK you want (a ';' or new line delimits each entry)
let ftss3 = [
["a";"aData"]
["b";"bData"]
]
which is
val ftss3: string list list = [["a"; "aData"]; ["b"; "bData"]]
i.e. a list of a list of strings.
(I'd try to use FSI to enter these things in, and see what the types are)
so to iterate this list of lists you would go
List.iter (fun xs ->
List.iter (fun x ->
printfn "%s" x)
xs)
ftss3
As pointed out in the existing answer, you probably want to represent your data as a list of lists, for which you need to use the ; delimiter (to make a list) rather than , to construct a singleton containing a tuple.
I would just add that if you want to perform an imperative action with each of the items, such as printing, then it is perfectly reasonable to use an ordinary for loop:
let ftss = [
["a"; "aData"]; ["b"; "bData"]
]
for nested in ftss do
for item in nested do
printfn "%s" item

Remove all occurrences of a value in a list in Erlang?

I have a list of values that looks something like this:
["Some", "random", "values", [], "in", "a", [], "list"].
I would like to create a new list with the empty list items removed. Like this:
["Some", "random", "values", "in", "a", "list"].
What is the easiest way of going about this? I assume using list comprehensions to build a new list is going to be the most efficient way of doing this. How would I filter this list using list comprehensions?
List comprehensions are a neater lists:filter/2:
[E || E <- List, E /= []]
This can be achieved using lists:filter.
List = ["Some", "random", "values", [], "in", "a", [], "list"],
lists:filter(fun(X) -> X /= [] end, List).
lists:filter takes a fun and a list. The fun should take a list item and return true or false. If the fun returns true the item is returned in the new list.
More information can be found here: http://erlangcentral.org/wiki/index.php?title=Filtering_Lists

Extract duplicates from nested list in SML

I have a function in SML that returns a nested list:
[["A", "B", "C"], ["A", "B"], ["B", "C"]]]
Is it possible to extract the elements that appear in these lists? i.e. output "B"?
I've tried something to the effect of List.filter (fn y=>(fn x=> x=y)) lst but to no avail..
Any hints?
I'll assume that the example nested list you give is representative, i.e., that elements are unique and ordered. I'll additionally leave out any explicit types or parameterized comparison functions, so the functions will operate on integers, not strings.
First, break down the problem down into comparing lists pairwise. Define a helper function common to find the common elements of a pair of ordered lists. It could look like this:
fun common(xs, []) = []
| common([], ys) = []
| common(x::xs, y::ys) = if x=y then x::common(xs, ys)
else if x < y then common(xs, y::ys)
else common(x::xs, ys)
It has type int list * int list -> int list.
To make this work for the nested list, you can base a solution on common, along the lines of:
fun nested_common([]) = []
| nested_common(x::[]) = x
| nested_common(x::y::rest) = nested_common(common(x,y)::rest)
This has type int list list -> int list.
Putting it to use (in Moscow ML):
- nested_common [[1,2,3], [1,2], [2,3]];
> val it = [2] : int list

Remove duplicate elements from a list in Erlang

How can I remove the duplicate from a list in Erlang?
Suppose I have a list like:
[1,1,2,3,4,5,5,6]
How can I get:
[1,2,3,4,5,6]
You could use sets, for example:
my_nonDuplicate_list1() ->
List = [1,1,2,3,4,5,5,6],
Set = sets:from_list(List),
sets:to_list(Set).
This returns [1,2,3,4,5], no more duplicates, but most likely not sorted.
Another possibility without the usage of sets would be:
my_nonDuplicate_list2() ->
List = [1,1,2,3,4,5,5,6],
lists:usort(List).
In this case it returns [1,2,3,4,5], no more duplicates and sorted.
And for those looking to preserve the order of the list:
remove_dups([]) -> [];
remove_dups([H|T]) -> [H | [X || X <- remove_dups(T), X /= H]].
A possible solution that will Preserve the order of the elements to help you learn how to manipulate lists, would involve two functions:
delete_all(Item, [Item | Rest_of_list]) ->
delete_all(Item, Rest_of_list);
delete_all(Item, [Another_item| Rest_of_list]) ->
[Another_item | delete_all(Item, Rest_of_list)];
delete_all(_, []) -> [].
remove_duplicates(List)-> removing(List,[]).
removing([],This) -> lists:reverse(This);
removing([A|Tail],Acc) ->
removing(delete_all(A,Tail),[A|Acc]).
To test,
Eshell V5.9 (abort with ^G)
1> mymod:remove_duplicates([1,2,3,1,2,4,1,2,1]).
[1,2,3,4]
2>
I would do something like this at first to preserve order, though it is not recommended. Remember that AddedStuff ++ Accumulator is OK but Accumulator ++ AddedStuff is really bad.
rm_dup(List) ->
lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
Acc ++ [Elem]
end
end, [], List
).
This solution is much more efficient if you want to preserve order:
rm_dup(List) ->
lists:reverse(lists:foldl(
fun(Elem, Acc) ->
case lists:member(Elem, Acc) of
true ->
Acc;
false ->
[Elem] ++ Acc
end
end, [], List
)).
for my opinion, the best option is to use lists:usort()
But in case you don't want to use BIF's, and you want the list to be sorted, I suggest a version of quick sort, in this implementation you will get the list sorted without duplicate values.
unique_sort([]) -> [];
unique_sort([Pivot|T]) ->
unique_sort ([X || X <- T, X < Pivot ) ]++
[Pivot] ++
unique_sort ([X || X <- T, X > Pivot ]).
Module sets has two functions that can be composed and do the job in an efficient way: sets:from_list/1 returns a set with all the elements of a list (with no duplicated elements from definition) and sets:to_list/1 returns a list with the elements of a set. Here is an example of use:
4> sets:to_list(sets:from_list([1,1,2,3,4,5,5,6])).
[3,6,2,5,1,4]
We could define the function as
nub(L) -> sets:to_list(sets:from_list(L)).

erlang list filter question

I have list - Sep1:
[
....
["Message-ID", "AAAAAAAAAAAAAAAAAAA"],
["To", "BBBBBBBBBBBBBBBBB"]
...
]
I try get element where first item = Message_ID for example:
lists:filter(fun(Y) -> (lists:nth(1,lists:nth(1,Y)) =:= "Message-ID") end, Sep1).
But i get error:
exception error: no function clause matching lists:nth(1,[])
in function utils:'-parse_to/1-fun-1-'/1
in call from lists:'-filter/2-lc$^0/1-0-'/2
But if i:
io:format(lists:nth(1,lists:nth(1,Sep1))).
> Message-ID
What's wrong?
Thank you.
It's better to change representation to [{Key, Value}, ...] so you can use lists:key* functions, proplists module, or convert it to dict with dict:from_list/1.
But if you still want to use lists:filter/2 you can filter list of lists by first element as following:
lists:filter(fun ([K | _]) -> K =:= "Message-ID" end, ListOfLists).
If you want to extract tails of lists which first element match with "Message-ID" you can use list comprehensions:
[Tail || ["Message-ID" | Tail] <- ListOfLists].
Why do you use two nested lists:nth calls?
lists:filter(fun(Y) -> lists:nth(1, Y) =:= "Message-ID" end, Sep1) works for me and returns a list containing the elements you want (lists where the first element is "Message-ID"). Just pattern match on that list to get the element you want, e.g. if you want only one such element you can do:
case lists:filter(fun(Y) -> lists:nth(1, Y) =:= "Message-ID" end, Sep1) of
[Result] -> % do something with it;
[] -> % no such element found
end
What you probably want is this:
[B || [A,B|_] <- L, A =:= "Message-ID"].
This does not assume any length of the nested lists:
It will return a list of the second elements of all inner lists whose first element is "Message-ID"
If you are sure there is only one "Message-ID" and want to throw an error otherwise:
[X] = [B || [A,B|_] <- L, A =:= "Message-ID"].
If you only want the first one (still throwing error when there is none):
[X|_] = [B || [A,B|_] <- L, A =:= "Message-ID"].
To understand what this code does I recommend reading official Erlang documentation about list comprehensions and the Learn You Some Erlang-chapter about the same topic: List Comprehensions.
Assuming that your list contains only elements each of them with 2 elements, you could use lists comprehension doing something like this:
1> L = [["Message-ID","AAAAAAAA"],["To","BBBBBBBBBBB"]].
[["Message-ID","AAAAAAAA"],["To","BBBBBBBBBBB"]]
2> [[A,B]||[A,B] <- L, A =:= "Message-ID"].
[["Message-ID","AAAAAAAA"]]
Hope this helps.
You could create your own filter (which doesn't care about the number of the elements):
filter(List) -> filter(List,[]).
filter([],Acc) -> lists:reverse(Acc);
filter([[]|Tail],Acc) -> filter(Tail,Acc);
filter([[H|T]|Tail],Acc) ->
case H =:= "Message-ID" of
true -> filter(Tail,[[H|T]|Acc]);
_ -> filter(Tail,Acc)
end.