Extract duplicates from nested list in SML - list

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

Related

How do I filter a list without using List.filter in OCaml?

I have to write a function that, given two lists, it returns a list of the elements of the first one whose square is present in the second one (sry for my english). I can't do it recursively and i can't use List.filter.
this is what i did:
let lst1= [1;2;3;4;5];;
let lst2= [9;25;10;4];;
let filquadi lst1 lst2 =
let aux = [] in
List.map(fun x -> if List.mem (x*x) lst2 then x::aux else []) lst1;;
It works but it also prints [] when the number doesn't satisfy the if statement:
filquadi lst1 lst2 ;;
- : int list list = [[]; [2]; [3]; []; [5]]
how can I return a list of numbers instead of a list of a list of numbers?
- : int list = [2;3;5]
You can use List.concat to put things together at the end:
List.concat (List.map ...)
As a side comment, aux isn't doing anything useful in your code. It's just a name for the empty list (since OCaml variables are immutable). It would probably be clearer just to use [x] instead of x :: aux.
As another side comment, this is a strange sounding assignment. Normally the reason to forbid use of functions from the List module is to encourage you to write your own recursive solution (which indeed is educational). I can't see offhand a reason to forbid the use of recursion, but it's interesting to combine functions from List in different ways.
Your criteria don't say you can't use List.fold_left or List.rev, so...
let filter lst1 lst2 =
List.fold_left
(fun init x ->
if List.mem (x * x) lst2 then x::init
else init)
[] lst1
|> List.rev
We start with an empty list, and as we fold over the first list, add the current element only if that element appears in the second list. Because this results in a list that's reversed from its original order, we then reverse that.
If you're not supposed to use recursion, this is technically cheating, because List.fold_left works recursively, but then so does basically anything working with lists. Reimplementing the List module's functions is going to involve a lot of recursion, as can be seen from reimplementing fold_left and filter.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
let rec filter f lst =
match lst with
| [] -> []
| x::xs when f x -> x :: filter f xs
| _::xs -> filter f xs

Haskell Function to multiply elements in a list

dobb[] = []
dobb (x:xs) = [x * 2| x<- xs]
I am really new to haskell and started learning it this week. I want to create a function that multiplies each element in a list by 2. So the list would go from [1,2,3] to [2,4,6]. The code I have works fine, except it skips the first element of the list and goes from [1,2,3] to [4,6]. How can I make the code multiply the first element as well?
[x*2 | x<-[1..5]]
I've found this line that does what I am looking for, but I dont understand how to go from this line of code and convert it to a function that works for all lists.
I'll address your last question,
how to go from this line of code,
[x*2 | x <- [1..5]]
and convert it to a function that works for all lists[?]
This is known as generalization and is achieved by abstraction. First we name it,
foo = [x*2 | x <- [1..5]]
then we name that arbitrary piece of data we used as an example to work on,
foo = let {xs = [1..5]} in [x*2 | x <- xs]
and then we abstract over it by removing that arbitrary piece of data in the internal definition, letting it become the function parameter instead, to be specified by this, now, function's callers:
foo xs = [x*2 | x <- xs]
and there it is, the general function working on all lists, doing the same thing as it did on the specific example we used at first.
If you use the pattern (x:xs) then you unpack the list such that x is the head (first item) of the list, and xs is the tail (remaining items) of that list. For a list [1,4,2,5], x will thus refer to 1, and xs to [4,2,5].
In the list comprehension, you then use x <- xs as a generator, and thus you enumerate over the remaining elements. The x in the list comprehension is furthermore not the head of the list, but a more locally scoped variable.
You can work with list comprehension and work on the entire list, so:
dobb :: Num a => [a] -> [a]
dobb xs = [x * 2| x <- xs]
We can also work with map :: (a -> b) -> [a] -> [b] to perform the same operation on the elements:
dobb :: Num a => [a] -> [a]
dobb = map (2*)

Lexicographically sorting a list of neasted lists

Consider the following nested list:
[["AXY"],["ABC","XYZ"],["EFG","ACF"]]
I would like to sort the list lexicographically by the first element of each inner list. The output should be:
[["ABC","XYZ"],["AXY"],["EFG","ACF"]]
If the task have been to sort only one list, I would use one of the methods in the following thread (link). But how can I sort a nested list?
Assuming you have a generic sort function taking a cmp function (like the one shown at the bottom of this answer), you just need to write one taking two string lists:
fun cmpnest ((x::xs):string list, (y::ys):string list) = if x > y then GREATER else LESS
| cmpnest ((x::xs):string list, nil) = GREATER
| cmpnest (nil, _) = LESS
After you have that, you can use it in your generic sort function:
- sort cmpnest [["AXY"], ["ABC", "XYZ"], ["EFG", "ACF"]];
> val it = [["ABC", "XYZ"], ["AXY"], ["EFG", "ACF"]] : string list list
As an addition to L3viathan's answer, you can also use String.compare:
fun cmpnest (x::_, y::_) = String.compare (x, y)
| cmpnest (_::_, []) = GREATER
| cmpnest ([], _) = LESS

Pattern matching to iterate over a list

I am trying to learn Haskell from Haskell Road to Logic
and came across this example:
mnmInt :: [Int] -> Int
mnmInt [] = error "empty list"ยท
mnmInt [x] = x
mnmInt (x:xs) = min x (mnmInt xs)
I understand the functions takes a list of Int -
Checks if empty
if not
checks if it's a list with 1 int if so return x
if not
plug mnmInt with xs parameter to min.
how does it reach the base case? what does the xs stand for?
min implementation:
min' :: Int -> Int -> Int
min' x y | x <= y = x
| otherwise = y
doesn't take an array.
(x:xs) is pattern matching syntax. Pattern matching lets you "destructure" data types and bind them to names. In this case x is the head of the list, and xs is the tail. min' doesn't need to take a list because x is the head of the list, not a list itself.
min' itself finds the minimum value between two Ints, mnmInt will eventually expand out to something like (min' 1 (min' 2 (min' 3 4))) if you pass in a list that looks like [1,2,3,4].
This is easy to see if you evaluate the code by hand, which I highly suggest you try. Remember, (x:xs) is two names, which are the head and tail of the list. You might want to play around with constructing lists using :
Here is an example that shows how pattern matching relates to code flow.
foo (x:y:[]) = "two"
foo ([]) = "none"
foo (_) = "some other value"
if you call foo [1,2] it will output "two", if you do foo [1,2,3] it will give you "some other value", and if you do foo [] it will return "none"
You can write a list in two ways in Haskell, first like [1,2,3,4,5], which is only syntactic sugar for 1:2:3:4:5:[].
Now the pattern (x:xs) matches with a list like this:
head(x:xs) = x
--> head [1,2,3,4,5] = head 1:2:3:4:5:[] = head 1:xs = 1
i hope this example make it clear to you how a list pattern works.

Pattern Matching and List Comprehension in List of Tuples

type a = [(Int,Int,Int,Int)]
fun:: a -> Int
func [a,b,c,d] = ?
I have a list of tuples like this what i required is to apply list comprehensions or pattern matching .. example taking sum or filter only divide 2 numbers ... i just want a start how to access values and or a list comprehension to this List of Tuples
To sum up the as, use something like this:
type A = [(Int, Int, Int, Int)]
func :: A -> Int
func tuples = sum [a | (a, b, c, d) <- tuples]
Also note that a type alias must begin with an upper case letter. Lower case letters are used for type variables.
hammar's answer covered list comprehensions, the basic schema for recursive functions using pattern matching is:
f [] = ..
f ((a,b,c,d):xs) = ..
So you need to specify a base case for a list containing no 4-tuples, and a recursive case for when the list consists of a 4-tuple (a,b,c,d) followed by a (possibly empty, possibly non-empty) list of 4-tuples xs. The pattern on the second line is a nested pattern: it first matches the list against a pattern like (x:xs), i.e. element x followed by rest of list xs; and then it matches x against the 4-tuple structure.
Below, I'll give some basic examples. Note that you can also write this with standard higher-order functions, such as filter and map, and I'm deliberaty not mentioning things like #-patterns and strictness. I do not recommend doing it like this, but it's just to give you an idea!
When you want to sum the first part of the tuples, you could do it like this:
sum4 :: [(Int,Int,Int,Int)] -> Int
sum4 [] = 0
sum4 ((a,b,c,d):xs) = a + sum4 xs
If you want to filter out the tuples where all of a,b,c and d are even:
filter4allEven :: [(Int,Int,Int,Int)] -> [(Int,Int,Int,Int)]
filter4allEven [] = []
filter4allEven ((a,b,c,d):xs)
| all even [a,b,c,d] = (a,b,c,d) : filter4AllEven xs
| otherwise = filter4AllEven xs
(If the use of all confuses you, just read even a && even b && even c && even d)
And finally, here's a function that returns all the even tuple components (tuples themselves can't be even!) in the same order as they appear in the argument list:
evenTupleComponents :: [(Int,Int,Int,Int)] -> [Int]
evenTupleComponents [] = []
evenTupleComponents ((a,b,c,d):xs) = [x | x <- [a,b,c,d], even x] ++ evenTupleComponents
Once you do a couple of exercises like these, you'll see why using standard functions is a good idea, since they all follow similar patterns, like applying a function to each tuple separately, including or excluding a tuple when it has some property or, more generally, giving a base value for the empty list and a combining function for the recursive case. For instance, I would write evenTupleComponents as evenTupleComponents = filter even . concatMap (\(a,b,c,d) -> [a,b,c,d]), but that's a different story :)