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.
Related
Running insert ls n should return a list of piles from taking ls and inserting n so that either n has been added to the head of the first pile in ls whose previous head is greater than or equal to n, or if it doesn't exist, a new pile containing just n is added to the end of ls.
For example,
insert [[4]; [5]] 3 = [[3;4]; [5]]
insert [[2]; [6]] 4 = [[2]; [4;6]]
insert [[3]] 4 = [[3]; [4]]
Basically, I'm trying to use the sort helper function that appends to the list if the element is less than the first in the list, and then in that case to just return the rest of the list.
let rec insert ls n =
match n with
| [] -> [x]
| y::ys -> if x < y then x::y::ys else y::insert x ys;;
let rec sort n =
match n with
| [] -> []
| x::xs -> insert x (sort xs);;
You keep confusing the order and type of arguments in your insert function. In your text description and following from the examples section, insert has type 'a list list -> 'a -> 'a list list, but when you try to write your insert function, you match the element n with a list. In the same manner, when you call insert from sort you pass the element as the first argument.
Next, your insert function shall return a list of lists, but in the first branch of your match, [] -> [x], you return just a list. In addition, there is no x variable bound in this match or anywhere else, probably you meant n?
Finally, when you compare the first element of the input list with the element n you compare the whole pile, instead of the head of the pile.
So let's try to rectify these problems, first of all, we have to match on ls instead of n,
let rec insert ls n =
match ls with
(* ^^
ls not n! *)
Next, if we have an empty input, then we need to return a list containing a single pile, where a pile is a list itself,
| [] -> [[n]] (* a list containing a list with a single element `n` *)
Finally, when we match on the head of the input list, we have to keep in mind that the head is the list itself, i.e., a pile, so we need to unpack it as well,
| (x::xs)::ys ->
(* ^^^^^^^
here x is the head of the pile, and x::xs is the whole pile *)
and pack it back,
if n < x then (n::x::xs)::ys else (x::xs)::insert ys n
(* ^^^^^^^^^^ ^^^^^^^
extended pile intact pile *)
The next step would be to make the match complete, i.e., to think what to do when the pile is empty itself (could it be?) and what to do when x is equal to n.
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 want to use 'head' function inside map.
The problem is the 'head' function only accepts non-empty list.
I have list of list:
let ll =[["dog", "cat"], ["pig", "cow"], []]
I need to iterate the list of list twice
let listOne = filter(\x -> if length x > 0) ll
map(\x -> head x) listOne
I'm wondering whether I can iterate the list of list once or put a "if condition" inside the map without the 'filter'
Any suggestion would be appreciated.
Yes, in fact you can write it as a list comprehension statement, and use pattern matching instead:
result = [ h | (h:_) <- ll ]
or as a function:
heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]
So here we use the pattern (h:_) which matches all non-empty lists, and we directly obtain the head h of such list and add it to the list. If you use a pattern in list comprehension (on the left side of the left arrow <-, it will skip the elements that do not match the pattern).
This is also more safe than using length, since length will get stuck into an infinite loop if you are working with infinite lists. Furthermore by using patterns over the non-total head function, we have more syntactical guarantees that this function will work (yes, once the non-empty elements are filtered, we are of course certain that head will not result in errors, but we only know this because we have information about the head function).
Note that your attempt will result in a syntax error, since you use an if, without a then and else part.
Alternatively, we can, like #DanielWagner says, write the heads function differently, for instance using:
heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll
or by using the bind of the list monad:
heads :: [[a]] -> [a]
heads = (take 1 =<<)
or we can transpose the 2d list. In that case the first row contains all the heads of the lists. Since it is however not guaranteed that there is such a row, we can append an empty list at the end, like:
heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose
I am trying to write a very simple function that takes a list (for example : [1,2,3,1,5]) and returns a list of elements that are directly after a specific element.
What I have reached so far is:
function element list = filter (\x -> element:x) list
My desired output:
function 1 [1,2,3,1,5]
=> [2,5]
Try this
map snd $ filter ((== x) . fst) $ zip theList (tail theList)
This won't work on an empty list, you will still need extra code to deal with that.
How does this work?
First, note that the values flow from right to left. The ($) operator allows this to happen. So, the first part evaluated is the zip function.
zip theList (tail theList)
For your example above, this would yield
zip [1,2,3,1,5] [2,3,1,5]
equaling
[(1,2), (2, 3), (3, 1), (1,5)]
which is the set of concurrent pairs in the list.
Next, the filter is applied
filter ((== x) . fst) $ ....
In English, what this says is, filter out only the concurrent pairs whose first element equals x. The output is
[(1,2), (1,5)]
Now we have the list of concurrent pairs starting with 1.
Finally, we apply the map
map snd $ ....
This just pulls out the second value of the pair.
map snd [(1,2), (1,5)] = [2,5]
which is the desired value.
Note, my comment above about failing on the empty list.
This is because tail crashes on the empty list
tail [] --error
There are ways to patch this behavior (see the safe package, for instance), but it is mostly bookkeeping at this point, so I left that for you to work out.
Also note that since all of the functions we used are lazy, this approach would work for lists of infinite length as well.
You can do this quite easily with a simple list comprehension, e.g.:
successors xs i = [y | (x,y) <- zip xs (drop 1 xs), x == i]
This will work to your specifications
next x (i:y:ys) -- look at the first two items in the list
| x == i = -- if the first item == x,
y : next x (y:ys) -- take the second, and continue minus the first element
|otherwise = -- not equal,
next x (y:ys) -- so skip that element
next _ [_] = [] -- if there's no second element, then stop
next _ _ = [] -- if the list is empty, stop
I'm tasked with creating a list of m word portmanteaus with n letter overlap from a given list of words.
For example, a 2 word 2 letter overlap portmanteau would be: "collegenetics" made from "college" and "genetics". A 3 word 2 letter overlap could be "firegaluminum" made of "fire", "regal" and "aluminum".
I have written a function singleport with this syntax:
let singleport word1 word2 n =
match suffix word1 n = prefix word2 n with
| false -> "No Port"
| true -> word1 ^ (prefixless word2 n)
which identifies whether or not two words could be portmanteaus. However, I'm struggling to identify a way to run this recursively in order to compare two elements of a list, all while constructing a new list that records all the possible portmantaus.
I figured List.fold_left could be used because of the use of the accumulator, but I don't know how to implement it and I would greatly appreciate any advice. Thank you very much!
One of the approaches to attack this task is to split it into small understandable subtasks, and then try to merge them. This is the deductive approach.
Deductively
Applying the deductive method to your task, we can split it in the following way:
create a list of consecutive pairs
map the list for portmanteaus
join the result
To create a list of pairs, you need to write the following function:
(** [pair_list xs] given the list [xs], produces a list of consecutive pairs.
Fails with an invalid argument, if the list has odd length. *)
val pair_list : 'a list -> ('a * 'a) list
With such a function, you can use map to transform each pair to a list of portmanteau, mapping a pair to an empty list, if it is impossible. E.g., given this function:
val portmanteau : (string * string) -> string list
And now we can join everything with List.concat:
let portmanteau_of_list xs =
List.map portmanteau (pair_list xs) |> List.concat
Inductively
Another approach is to move from the opposite direction, i.e., not from top to down, but from the bottom. So inductive reasoning about this task would be the following:
portmanteaus of an empty list is an empty list,
portmanteaus of the list of one element is an error
portmanteaus of a list that is greater than two when the first two elements don't form a portmanteau is the portmanteaus of the rest elements of the list
portmanteaus of a list greater than two when the first two elements form a portmanteau is the portmanteaus of these two elements plus portmanteaus of the rest elements of the list.
The same in OCaml (untested):
let rec portmanteau_of_list = function
| [] -> []
| [_] -> failwith "odd list"
| x :: y :: xs -> match portmanteau x y with
| None -> portmanteau_of_list xs
| Some p -> p :: portmanteau_of_list xs