How can I delete the element elem in list L? If the list does not contain elem, then the function should return the list unchanged.
For instance:
L = [1, 3, 4, 0, 5, 7]
elem = 5
So far I have the following function:
fun removeElem elem myList[] = myList
| removeElem (myList::tl) = if mem myList elem then
rm elem myList[]
else
removeElem elem tl
You can turn the question around and ask how to keep only those items not equal to elem. This fits cleanly with filter:
fun removeElem elem myList = filter (fn x => x <> elem) myList
This code will accomplish what you want to do: remove the element (actually it will remove all instances of the element if there are more than one) and return the rest of the list as-is:
fun remove_element (list, element) =
case list of
[] => []
| list_head::list_tail => let val a = remove_element(list_tail, element)
in
if list_head = element
then a
else list_head::a
end
fun delete (s,[]) = []
| delete (s,x::xs') =
if s = x then xs' (* more efficient than call delete function again *)
else x::delete(s, xs')
fun remove_element (elemlist, elem) =
case elemlist of
[] => []
| head::tail => if elem = head
then remove_element (tail, elem)
else head::remove_element (tail, elem)
Output SML/NJ:
val remove_element = fn : ''a list * ''a -> ''a list
val it = () : unit
(* matching *)
- remove_element ([1,2,3,4,5], 4);
val it = [1,2,3,5] : int list
(* non matching *)
- remove_element ([1,2,3,4,5], 7);
val it = [1,2,3,4,5] : int list
(* multiple instances *)
- remove_element ([1,3,4,4,5],4);
val it = [1,3,5] : int list
With no libraries or extra functions
fun remv(L, c) =
if null(L) then nil
else if c=hd(L) then remv(tl(L), c)
else hd(L)::remv(tl(L), c);
You can try this code.
fun remove_element (elemlist:int list, elem:int) =
case elemlist of
[] => []
| head::tail => if elem = head
then remove_element (tail, elem)
else head::remove_element (tail, elem)
also you can use this function to remove duplicate entries from a list:
fun remove_duplicates(xs: ''a list) =
let
fun helper(ds: ''a list, m: ''a) =
if null ds
then []
else if hd ds = m
then helper(tl ds, m)
else hd ds :: helper(tl ds, m)
in
if null xs
then []
else hd xs :: remove_duplicates( helper(tl xs, hd xs) )
end
Related
I implement function which adds an element once to every list of a list.
example:
f :: a -> [[a]] -> [[[a]]]
f 7 [[1],[2],[3]]
[[[7,1],[2],[3]],[[1],[7,2],[3]],[[1],[2],[7,3]]]
I start with this solution:
f :: a -> [[a]] -> [[[a]]]
f e xs = ((\n -> (\(x,l)-> if x==n then e:l else l) <$> zip [1..] xs) <$> [1..length xs])
Can you please provide some more nice implementations of this function?
You can implement this with recursion. As base case we consider an empty list:
f _ [] = []
for non-empty lists (x:xs) we can use the first item, which is the first sublist. We thus can produce a list where we prepend the first sublist x with the element e, followed by the remaining items xs, so (e:x) : xs is the first item. For the remaining items we recurse on the tail of the list xs and will for each sublist prepend this with the sublist x:
f e (x:xs) = ((e:x) : xs) : map (x:) (f e xs)
so putting these together gives us:
f :: a -> [[a]] -> [[[a]]]
f _ [] = []
f e (x:xs) = ((e : x) : xs) : map (x:) (f e xs)
Write splits which gives all possible ways of splitting a list
splits :: [a] -> [([a], [a])]
splits xs = zip (inits xs) (tails xs)
for example
> splits "abc"
[("","abc"),("a","bc"),("ab","c"),("abc","")]
and using it write a function that operates on each element of a list
onEach :: (a -> a) -> [a] -> [[a]]
onEach f xs = [ys ++ f z : zs | (ys, z:zs) <- splits xs]
like this
> onEach toUpper "abc"
["Abc","aBc","abC"]
and now f is just
f :: a -> [[a]] -> [[[a]]]
f x = onEach (x:)
Answer of David Flercher with onEach :: (a -> a) -> [a] -> [[a]] very interesting, I do some generalization with typeclass, I think this is usefull when we need some versions of objects mutated in one parameter..:
class Eachable e where
each :: (a -> a) -> e a -> [e a]
Now we can each on different types for example on Lists:
instance Eachable [] where
each _ [] = []
each g (x:xs) = ((g x) : xs) : map (x:) (each g xs)
each (+1) [1,2,3]
[[2,2,3],[1,3,3],[1,2,4]]
and Trees
data Tree a = Empty | Node (Tree a) a (Tree a) deriving Show
instance Eachable Tree where
each _ Empty = []
each g t#(Node l a r) = (\i -> e g 1 i t) <$> [1..count t] where
e _ _ _ Empty = Empty
e g c i (Node l a r) = Node l' a' r' where
a' = if c==i then g a else a
l' = if c==i then l else e g (c+1) i l
r' = if c==i then r else e g (c+(count l)+1) i r
count Empty = 0
count (Node l _ r) = 1 + count l + count r
tr = Node (Node Empty 1 Empty) 2 (Node Empty 3 Empty)
each (+1) tr
[Node (Node Empty 1 Empty) 3 (Node Empty 3 Empty),Node (Node Empty 2 Empty) 2 (Node Empty 3 Empty),Node (Node Empty 1 Empty) 2 (Node Empty 4 Empty)]
and others:
data Animal a = Animal {speed::a,size::a,smart::a} deriving Show
instance Eachable Animal where
each g (Animal sp sz sm) = [Animal (g sp) sz sm, Animal sp (g sz) sm, Animal sp sz (g sm)]
each (+1) $ Animal 1 1 1
[Animal {speed = 2, size = 1, smart = 1},Animal {speed = 1, size = 2, smart = 1},Animal {speed = 1, size = 1, smart = 2}]
I am very new to SML/NJ and I am kind of lost. I have been trying to implement a function that is going to search through the list of tuples that have some lists in it, for example:
val x = [(5, 2, [9 , 8, 7]), (3, 4, [6, 5, 0]), (11, 12, [8, 3, 1])]
I would like my function to add the first element of the tuple to the new list once there is a match between my target number and a number in element 3 of the tuple. I have tried several implementations, but none of them work properly so far.
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
val a: int list = nil;
fun findNum(nil) = a | findNum (x: id list) =
let val tem = hd(x)
val theList = #3tem
val i = #1tem
fun findMatch(nil) = a | findMatch(tem) =
if (number = hd(theList)) then i::a
else findMatch (tl(theList))
in findNum(tl(x))
end;
findNum(b);
I know it is badly written, and that is why it keeps returning an empty list. I feel like I need to do "if else" instead of let/in/end so it will recursively call the rest of the tuples in the list. My problem is that I am not sure how to do it because if I use if/else then I cannot declare some value inside the function. I appreciate any suggestions or hints.
Thank you.
You might start with a function member (x, xs) that is true if x is an element in the list xs:
fun member (x, xs) = List.exists (fn y => x = y) xs
A base case is when the list of three-tuples is empty. Then x does not occur in the third element of any of the (non-existing) three-tuples, and the list of results is empty. A recursive case is achieved by pattern matching against the first element of the list being a three-tuple, (i,j,xs), and the tail of the list, ts, and ask if x is a member of that third element xs; if it is, return the first part of the tuple, i:
fun find (x, []) = []
| find (x, (i,j,xs)::ts) =
if member (x, xs)
then i :: find (x, ts)
else find (x, ts)
A shorter version using the higher-order list combinators map and filter:
fun find (x, ts) = map #1 (filter (fn (i,j,xs) => member (x, xs)) ts)
Here is my implementation with some slight changes:
type id = int* int* int list;
val b:id list = [(5,2,[9,8,7]), (3,4,[6,5,0]), (11, 12, [8,3,1])]
val number: int = 8;
fun findNum [] = []
| findNum (x::xs) =
let
val theList :int list = #3 (x :id)
val i : int = #1 x
fun findMatch [] = false
| findMatch (y::ys) = if (number = y) then true
else findMatch ys
in
if (findMatch theList = true) then i ::(findNum xs)
else (findNum xs)
end;
Example:
- findNum b;
val it = [5,11] : int list
I've been asked to write a Standard ML Program which deletes every occurrence of a list from another list. For the life of me I cannot understand what is wrong with my code. Any help would be appreciated!
My input for this program is as follows:
deleteAll [1,2,3] [3,2,1,2,3,2,1,2,3];
However my output is this:
val it = [3,2,2,1,2,3] : int list
When it should be: [3,2,2];
fun length(x) = if x = [] then 0 else 1+length(tl(x));
val length = fn : ''a list -> int
fun drop 0 L = L
| drop n [] = raise c4
| drop n (h::t) = drop (n-1) t;
val drop = fn : int -> 'a list -> 'a list
fun starts [] _ = true
| starts _ [] = false
| starts (h::t) (x::xs) = if(h=x) then starts t xs else false;
val starts = fn : ''a list -> ''a list -> bool
fun deleteAll [] _ = []
| deleteAll xs [] = xs
| deleteAll (x::xs) (y::ys) = if(starts (x::xs) (y::ys))
then deleteAll (x::xs) (drop (length(x::xs)) (y::ys))
else y::(deleteAll (x::xs) ys);
val deleteAll = fn : ''a list -> ''a list -> ''a list
First you don't need to create a length function as length is a build-in function that returns an int representing the elements of an 'a list.
One more thing, you raise an exception c4 in your function drop. Then you should also include that in the beginning of your program.
The primary reason your code doesn't work is your deleteAll function base cases. The corrected version should be:
fun deleteAll [] xs = xs (* when the first list is empty, it should return the original list *)
| deleteAll xs [] = [] (* when the second list is empty, it should return an empty list *)
| deleteAll (x::xs) (y::ys) = if(starts (x::xs) (y::ys))
then deleteAll (x::xs) (drop (length(x::xs)) (y::ys))
else y::(deleteAll (x::xs) ys);
The rest is good! After the change the answer should be correct : )
- deleteAll [1,2,3] [3,2,1,2,3,2,1,2,3];
val it = [3,2,2] : int list
I cannot figure out which case I am missing here,for my functions,can someone help me find which case to consider also so that I do not get the match non-exhaustive error.It is taking time for me to really figure out which part is missing.
fun eval_1 (nil,_) = nil
| eval_1 (_,nil) = nil
|eval_1 ((x::h::xs),(y::t::ys)) = if x = ~1 then (h,t)::eval_1(xs,ys) else(x,y)::eval_1(h::xs,t::ys);
fun eval_2 (nil,_) = nil
| eval_2 (x,nil) = nil
|eval_2 ((x),(y::ys)) = eval_1 (x,y)::eval_2(x,ys);
fun eval_3 (nil,_) = nil
| eval_3 ((x::nil),nil) = nil
| eval_3 ((x::xs),(ys)) = eval_2(x,ys)::eval_3(xs,ys);
Matching on (x:xs, y:ys) instead of ((x::h::xs),(y::t::ys)) gets rid of the non-exhaustive warning. To make the rest of the code equivalent you can use hd and tl from List to get the head of the tail and the tail of the tail instead of decomposing the list with x::next::xs.
fun eval_1 (nil,_) = nil
| eval_1 (_,nil) = nil
| eval_1 (x::xs, y::ys) = if x = ~1 then (hd xs, hd ys)::eval_1(tl xs, tl ys) else (x,y) :: eval_1(xs, ys)
fun eval_2 (nil,_) = nil
| eval_2 (x,nil) = nil
| eval_2 ((x),(y::ys)) = eval_1 (x,y)::eval_2(x,ys);
fun eval_3 (nil,_) = nil
| eval_3 ((x::nil),nil) = nil
| eval_3 ((x::xs),(ys)) = eval_2(x,ys)::eval_3(xs,ys);
Sample run:
> val eval_1 = fn : int list * 'a list -> (int * 'a) list
val eval_2 = fn : int list * 'a list list -> (int * 'a) list list
val eval_3 = fn : int list list * 'a list list -> (int * 'a) list list list
val it = () : unit
> eval_1([1,2,3], [4,5,6]);
val it = [(1, 4), (2, 5), (3, 6)] : (int * int) list
I want to go through an array and return a list of ints (the value of indexes) when a value in the array matches true.
The array is a boolean array of just true/false values.
let get_elements (i:int)(b:bool) : int =
if b = true then (i::l)
else (())
;;
let rec true_list (b: bool array) : int list =
(fun i l -> get_elements i l)
;;
The syntax is wrong for my code and I am confused on exactly how to return a list of ints.I only want to return the indexes of those elements that are true in the array.
You refer to 'l' in get_elements, but it's not in the scope of that function.
Here's an approach using a ref to an integer list (a mutable list):
boolarray = [|true; false; true; false; false; true|] ;;
type ilist = (int list) ref ;;
let intlist () : ilist = ref [] ;;
let push ( l: ilist) (x: int) : unit = l := x::(!l) ;;
let lst = intlist () ;;
Array.iteri ( fun i b -> if b = true then (push lst i )) boolarray ;;
!lst ;; (* => int list = [5; 2; 0] *)
Or, if you'd rather avoid refs (which is usually a good idea) this is cleaner:
let get_true_list (b: bool array) : int list =
let rec aux i lst =
if (i = Array.length b) then lst else
(if b.(i) = true then ( aux (i+1) (i::lst)) else (aux (i+1) lst)) in
aux 0 [] ;;
(* using boolarray defined above *)
get_true_list boolarray ;; (* => int list = [5; 2; 0] *)
I present an example which does not use state, avoids the 'if then else' construct making it easier to read and verify.
let mylist = [| true; false; false; true; false; true |] in
let get_true_indexes arr =
let a = Array.to_list arr in
let rec aux lst i acc = match lst with
| [] -> List.rev acc
| h::t when h = true -> aux t (i+1) (i::acc)
| h::t -> aux t (i+1) acc
in
aux a 0 []
in
get_true_indexes mylist