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.
Related
I have the requirement
add_items(AuctionId, [{Item, Desc, Bid}]) -> {ok, [{ItemId, Item]} | {error, unknown_auction}.
How do I use the list of tuples to write my function body?
What I've tried:
add_items(AuctionId, ItemList) -> ...
This works fine, but I haven't matched the requirement - but the requirement returns a function_clause error if I define it that way as it cannot be pattern-matched (and I don't think the question wants me to define the specification this way either as I would write something like
-spec add_items(reference(), [item_info()]) ->
{ok, [{itemid(), nonempty_string()}]} | {error, unknown_auction()}.
It also does not match say trying to do a recursion definition with a head and a tail ala [] and [H|T]
Here's an example of what you can do:
-module(a).
-compile(export_all).
%%add_items(AuctionId, [{Item, Desc, Bid}]) ->
{ok, [{ItemId, Item]} | {error, unknown_auction}.
add_items(AuctionId, Items) ->
case valid_auction(AuctionId) of
true -> insert_items(Items, _Results=[]);
false -> {error, unknown_auction}
end.
%% Here you should check the db to see if the AuctionId exists:
valid_auction(AuctionId) ->
ValidAuctionIds = sets:from_list([1, 2, 3]),
sets:is_element(AuctionId, ValidAuctionIds).
%% Here's a recursive function that pattern matches the tuples in the list:
insert_items([ {Item, Desc, Bid} | Items], Acc) ->
%%Insert Item in the db here:
io:format("~w, ~w, ~w~n", [Item, Desc, Bid]),
ItemId = from_db,
insert_items(Items, [{ItemId, Item} | Acc]);
insert_items([], Acc) ->
lists:reverse(Acc).
In the shell:
8> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,a}
9> a:add_items(4, [{apple, fruit, 10}]).
{error,unknown_auction}
10> a:add_items(1, [{apple, fruit, 10}, {cards, game, 1}]).
apple, fruit, 10
cards, game, 1
[{from_db,apple},{from_db,cards}]
11>
The shell interaction demonstrates that add_items() satisfies your requirement:
It takes two arguments, with the second argument being a list whose elements are three element tuples.
The return value is either an ok tuple containing a list of two element tuples; or the tuple {error,unknown_auction}.
I have Erlang function that returns the last element of a list
lastElement([H|[]]) ->H;
lastElement([H|T]) ->lastElement(T).
and a function that returns a list without last element
withoutLastElement([H|[]], Result) ->Result;
withoutLastElement([H|T]) ->withoutLastElement(T, [H|Result]).
so i browse the same list for two times, and for more efficiency i want to do only a function that returns the last element of a list and returns this list without this element in one browse, this is easy in another language but i can't do that in Erlang so any help and thank you all.
You'd usually return the two values in a tuple:
list_and_last(List) ->
list_and_last(List, []).
list_and_last([H], Result) ->
{H, Result};
list_and_last([H|T], Result) ->
list_and_last(T, [H|Result]).
Calling list_and_last with [1,2,3] returns {3,[2,1]}.
In Erlang you can return a tuple, so you simply define a tuple with the last element and the list:
... -> {last_element, list}
You retrieve the value with pattern matching:
{Element, List} = last_element_and_new_list(The_List)
The last element and list will be bound to the respective variables. Note that you can return more than two values in a tuple.
You can simply reverse the list:
List = [1, 2, 3, 4, 5, 6],
[Last | Rest] = lists:reverse(List)
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.
Say I have one unordered list
val unsorted = List("third", "second", "fourth", "first")
And I have another list that has the indices of the above list in the proper order
val ids = List(3, 1, 0, 2)
How can I sort unsorted using these indices to get this result
List("first", "second", "third", "fourth")
Simply map the ids onto the unsorted list itself.
scala> val sorted = ids map unsorted.toIndexedSeq
sorted: List[String] = List(first, second, third, fourth)
Converting unsorted to an IndexedSeq is not necessary, but as #gzm0 points out below it prevents this operation from being O(n^2).
I am trying to do basic list operations with SML.
I want to extract each element of the list and append string to that element and add it back to the list.
Example:
List : [A,B,C,D]
String : A
Final List: [AA,AB,AC,AD]
How can I iterate through each element in the list in SML? I can append strings using ^ and concatenate lists using # but how do I extract each element from the list?
Also can we use something like map or arrays to store these list values and pass it to different functions in SML?
I could just find some vague information about map and no definite information as to how we can use it.
two easy ways to do this:
- fun addstring (x::xs) a = (a^x) :: addstring xs a
= | addstring [] a = []
= ;
val addstring = fn : string list -> string -> string list
- addstring ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
The above uses pattern matching to destruct the list, performs the operation, then constructs the list again, recursing as it goes.
- fun addstring2 xs a = map (fn x => a^x) xs;
val addstring2 = fn : string list -> string -> string list
- addstring2 ["A", "B", "C", "D"] "A";
val it = ["AA","AB","AC","AD"] : string list
This one is a fair bit simpler (if perhaps a tiny bit harder to read than the explicit cases in addstring.) but it shows how map is used - you specify a function that maps each element from the source to the target domain, give it a list of elements in the source domain, and it returns a list in the target domain.
of course, neither of these do in-place updating of the list, they return the new list.