I'm having trouble understanding why my function seems to loop endlessly in my recursion:
-module(list_tut).
-export([print_cities/1]).
-author("kimput").
print_cities([]) ->
ok;
print_cities([H|T]) ->
io:format('city: ~p~n', [H]),
[H|print_cities([T])].
If I enter a list of cities like:
> list_tut:print_cities(['Moscow', 'Tokyo', 'Stockholm']).
It prints all the items rather quickly and then keeps printing cities: [].
I understand this is an absolute beginner's question, but I've been looking at this problem for a long time now and can't figure out a way of solving it without adding tail-recursion or something similar.
This is because you're recursing with [T] instead of T. T is the tail of the list which is already a list (if the list is not an improper list). Your code is wrapping the tail in another list, which means in addition to an infinite recursion, the initial elements printed are also wrong:
1> c(list_tut).
{ok,list_tut}
2> list_tut:print_cities(['Moscow', 'Tokyo', 'Stockholm']).
city: 'Moscow'
city: ['Tokyo','Stockholm']
city: []
city: []
city: []
city: []
city: []
...
Changing [H|print_cities([T])]. to [H|print_cities(T)]. fixes this:
-module(list_tut).
-export([print_cities/1]).
-author("kimput").
print_cities([]) ->
ok;
print_cities([H|T]) ->
io:format('city: ~p~n', [H]),
[H|print_cities(T)].
1> c(list_tut).
{ok,list_tut}
2> list_tut:print_cities(['Moscow', 'Tokyo', 'Stockholm']).
city: 'Moscow'
city: 'Tokyo'
city: 'Stockholm'
['Moscow','Tokyo','Stockholm'|ok]
I'm not sure why you're recreating the list in a print function, but if you want the original list back, the [] case should return [] if you want the final return value to be the same as the initial one.
...
print_cities([]) ->
[];
...
1> c(list_tut).
{ok,list_tut}
2> list_tut:print_cities(['Moscow', 'Tokyo', 'Stockholm']).
city: 'Moscow'
city: 'Tokyo'
city: 'Stockholm'
['Moscow','Tokyo','Stockholm']
Related
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
I have a list like this and i would like to find the word fruit and extract "Apple" and {"1"}. The list can be of varying size.
List = [{{"1"},{fruit,"Apple"}},{{"2"},unknown},{{"3"},{vegetable,"Potato"}}]
You should read some basic Erlang book to start. for example LearnYouSomeErlang.
Your problem is often solved using pattern matching in a list comprehension, here is an example directly in the shell:
1> List = [{{"1"},{fruit,"Apple"}},{{"2"},unknown},{{"3"},{vegetable,"Potato"}}].
[{{"1"},{fruit,"Apple"}},
{{"2"},unknown},
{{"3"},{vegetable,"Potato"}}]
2> [{Fruit,Qty} || {{Qty},{fruit,Fruit}} <- List ].
[{"Apple","1"}]
3>
Here is a solution that uses several function clauses instead of a list comprehension:
-module(my).
-compile(export_all).
get_list() ->
[
{{"1"},{fruit,"Apple"}},
{{"2"},unknown},
{{"3"},{vegetable,"Potato"}},
{{"2"},{fruit,"Banana"}}
].
process_list([]) ->
[];
process_list([ {{N}, {fruit, Fruit}} | Tail]) ->
[{N, Fruit} | process_list(Tail) ];
process_list([_Head | Tail]) ->
process_list(Tail).
In the shell:
7> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
8> my:process_list(my:get_list()).
[{"1","Apple"},{"2","Banana"}]
The second function clause tries to match a tuple at the head of the list containing the atom fruit. If the head of the list is a tuple containing fruit, then the quantity and the type of the fruit is added to a results list.
If the second function clause doesn't match, i.e. the head of the list is a tuple that does not contain the atom fruit, then the third function clause will match, and it discards the head of the list.
Finally, when you get to the end of the list, the first function clause will match, and it returns the empty list, which neatly gets cons'ed to the end of the result list, making it a proper list.
Another way to solve the problem is to introduce an accumulator to gather the results:
process_list(L) ->
process_list(L, []). %The empty list for the second argument is the accumulator.
process_list([], Acc) ->
lists:reverse(Acc);
process_list([ {{N}, {fruit, Fruit}} | Tail], Acc) ->
process_list(Tail, [ {N,Fruit} | Acc ]); %Add the match to the accumulator.
process_list([_Head | Tail], Acc) ->
process_list(Tail, Acc).
As you can see in Pascal's example, Erlang's list comprehensions can accomplish the same thing in a very brief amount of code.
I want to retrieve id(which is 1 in this case) for the first appearing "Apple" in a list. For example:
List = [["1","Apple"],["2","Orange"],["3","Apple"]].
In Erlang world, for fixed-size data types we use tuples. Your List may grow up but i thinks its elements are fixed-size, So i recommend to use tuple for its elements and you can use API functions of modules lists and proplists:
1> List = [{"1", "Apple"}, {"2", "Orange"}, {"3", "Apple"}].
[{"1","Apple"},{"2","Orange"},{"3","Apple"}]
%% Search in List for a tuple which its 2nd element is "Apple":
2> lists:keyfind("Apple", 2, List).
{"1","Apple"}
3> lists:keyfind("Unknown", 2, List).
false
%% Take first Tuple which its 2nd element is "Apple", Also yield Rest of List:
4> lists:keytake("Apple", 2, List).
{value,{"1","Apple"},[{"2","Orange"},{"3","Apple"}]}
%% Replace a tuple which its 1st element is "3" with {"3", "Banana"}
5> lists:keyreplace("3", 1, List, {"3", "Banana"}).
[{"1","Apple"},{"2","Orange"},{"3","Banana"}]
A simple recursive function is probably what you're looking for here.
find_key([], _) -> error;
find_key([[Key, Value] | Rest], Search) when Value = Search -> Key;
find_key([_ | Rest], Search) -> find_key(Rest, Search).
You can use lists:search/2 for that:
List = [["1","Apple"],["2","Orange"],["3","Apple"]],
{value, [Id, "Apple"]} =
lists:search(fun([Id, Name]) -> Name == "Apple" end, List),
Id.
I have a List[T] where the datas inside are like below:
[0]- id : "abc", name: "xyz", others: "value"
[1]- id : "bcd", name: "dsf", others: "value"
Now I want to return the same List[T] but with the id and names i.e the returning List will be:
[0]- id : "abc", name: "xyz"
[1]- id : "bcd", name: "dsf"
I tried with below code:
var temps = templates.map(x => List("id" -> x.id, "name" -> x.name))
But it it produces List inside List i.e:
[0]-
[0] id : "abc"
[1] name: "xyz"
[1]-
[0] id : "bcd"
[1] name: "dsf"
I tried with tuple also but in vain. How can i just map my list such that everything is cleaned out except the id and name value pair??
Unless you want to define a new class with just the id and name fields, I think tuples would be your best bet:
scala> case class obj(id: String, name: String, others: String)
defined class obj
scala> val l = List(new obj("abc", "xyz", "value"), new obj("bcd", "dsf", "value"))
l: List[obj] = List(obj(abc,xyz,value), obj(bcd,dsf,value))
scala> l.map(x => (x.id, x.name))
res0: List[(String, String)] = List((abc,xyz), (bcd,dsf))
Also you are actually using tuples in your example, the -> syntax creates tuples in Scala:
scala> "a" -> "b"
res1: (String, String) = (a,b)
Here is the "define another class" option:
scala> case class obj2(id: String, name: String){
| def this(other: obj) = this(other.id, other.name)
| }
defined class obj2
scala> l.map(new obj2(_))
res2: List[obj2] = List(obj2(abc,xyz), obj2(bcd,dsf))
Given that the List[T] is a List[Map], then you may able to do the following:
//Remove the "others" key.
val temps = templates.map( map => {map - "others"})
I think its pretty clear that your list contains objects with three members: id, name, others. Hence you access them by using
{x => x.name}
What I am not so sure about, is how you imagine your end result. You obviously need some data structure, that holds the members.
You realized yourself, that its not very nice to store each objects members in a list inside the new list, but you seem to not be ok with tuples?
I can imagine, that tuples are just what you want.
val newList = oldList.map{e => e.id -> e.name}
results in alist like this:
List(("id_a", "name_a"), ("id_b", "name_b"), ("id_c","name_c"))
and can be accessed like this(for example):
newList.head._1
for the first tuples ids, and
newList.head._2
for the first tuples name.
Another option could be mapping into a map, since this looks pretty much like, what you want in the first place:
newMap = oldList.map{e => e.id -> e.name}.toMap
This way you can access members like this newMap("key") or safer: newMap.get("key") which returns an option and wont end up in an exception, if the key doesn't exist.
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.