List processing
The material for this page was originally written for isaac computer science |
A list is an abstract data type that holds items in a given order. The same item may be be in the same list multiple times. For example the following are lists:
[9,2,3,4,4,3,7,8]
[65,75,3,65,0]
["cabbage", "potato", "boat", "helmet", "boat"]
An empty list is defined by empty parenthesis:
[]
Lists can also contain other lists:
[[1,2,3], [6,3,8], [9,10,3]]
In Haskell the items contained in a list must all be of the same datatype.
Extension: Data types and lists Whilst some programming languages such as Haskell will only allow datatype for the items in a list, it is sometimes possible to have multiple datatypes in a list. Whilst this might be possible it might not be a good idea and can make some very hard to debug code. For example, in python we might have an unexpected output from some very simple looking code: .> myList = ['-92', 9, 5]
.> min(myList)
5
|
Making and checking a list
editYou can perform a range of functions on lists:
You can make an empty list:
.> someList = []
.> someList
[]
You can make a list that contains items:
myList = [20,3,51,6,3,7]
You can get the length of a list:
.> myList = [20,3,51,6,3,7]
.> length myList
6
You can check if a list is empty
.> myList = [20,3,51,6,3,7]
.> null myList
False
.> someList = []
.> null myList
True
Chopping up a list
edit
Some very common list commands are head and tail. If you treat a list like a snake, head will give you the first item in the list (its head), and tail will remove the head of the snake and give you the rest a new list.
.> myList = [20,3,51,6,3,7]
.> head(myList)
20
.> myList = [20,3,51,6,3,7]
.> tail(myList)
[3, 51, 6, 3, 7]
You can combine multiple head and tail commands together
.> myList = [20,3,51,6,3,7]
.> head(tail(tail(myList)))
51
Example: combining multiple head and tail commands In the above example we start from the innermost function, in this case
The command
We now move to next innermost function:
The command
This leaves us with only one more function to calculate. We know the
|
Adding to lists
editPrepend (:) an item to another list, i.e. stick a single element on the front, add a new head to a list:
.> myList = [20,3,51,6,3,7]
.> 5 : myList
[5, 20, 3, 51, 6, 3, 7]
.> "c" : ["a", "t"]
["c", "a", "t"]
.> 1 : 2 : myList
[1, 2, 20, 3, 51, 6, 3, 7]
Extension: Type mismatch when dealing with strings, characters and lists You might be used to other programming languages treating single and double quotation marks in much the same way, for example in Javascript: .> a = "Double quotation marks with a single (') in the middle"
.> b = 'Single quotation marks with a double (") in the middle'
.> a == b
True
This isn't the case for Haskell. Haskell treats the single quotation mark (') as defining a single element, and the double quotation marks (") as defining a list, even if there is only a single element inside the double speech marks, e.g.
.> "cat"
"cat"
.> ['c','a','t']
"cat"
.> ['c','a','t'] == "cat"
True
But .> ["c","a","t"] == "cat"
error:
* Couldn't match type `Char' with `[Char]'
Expected type: [[Char]]
Actual type: [Char]
And we can see that .> ["c","a","t"] == [['c'],['a'],['t']]
True
Prepending the list .> "c" : ["a", "t"]
["c", "a", "t"]
We can also do the same when prepending an item of type .> 'c' : ['a', 't']
"cat"
But attempting to prepend an item of type Char .> 'c' : ["a", "t"]
* Couldn't match expected type `Char' with actual type `[Char]'
* In the expression: "a"
In the second argument of `(:)', namely `["'a", "t"]'
In the expression: 'c' : ["'a", "t"]
|
Append (++) an item or a list to another list, i.e. stick something on the end, maybe an item or another list:
.> myList = [20,3,51,6,3,7]
.> myList ++ 99
[20, 3, 51, 6, 3, 7, 99]
.> myList ++ [5, 4, 3, 2]
[20, 3, 51, 6, 3, 7, 5, 4, 3, 2]
The prepend command (:) only allows you to add a single element onto the front of a list. If you want to add a list onto the front of another list you can use the append (++) command:
.> listA = ["x", "y", "z"]
.> listB = ["d", "c"]
.> listA ++ ["e"]
["x", "y", "z", "e"]
.> listA ++ listB
["x", "y", "z", "d", "c"]
You can use a combination of append and prepend to combine multiple lists and items
.> "hello" ++ " " ++ "world"
"hello world"
.> '!' : "shocking" ++ "this" ++ ['w', 'o', 'r', 'k', 's'] ++ "!"
"!shockingthisworks!"
Exercise: Lists What does the following haskell code output: myList = [3,4,5,3,4,6]
head(tail(tail(myList)))
Answer: 5
What does the following haskell code output: myList = ['a', 'b', 'c', 'd']
tail(myList)
Answer: ['b', 'c', 'd'] or "bcd"
What does the following haskell code output: myList = ["cat", "mouse", "moose", "cow", "sheep"]
length(tail(tail(tail(myList))))
Answer: 2
What does the following haskell code output: myList = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"]
null(head(tail(tail(myList))))
length(tail(head(tail(tail(myList ++ ["black", "white"])))))
Answer:
Note that when we take the tail of a single element list containing a string, it treats the string as a list.
Given a list called Answer:
head(tail(tail(tail(containsPrime))))
Answer:
let someList = ["badger", "fish", "vole"]
tail(tail(someList ++ ["frog"]))
What does the following code do: .> listA = [1, 2, 3]
.> listB = [9, 8]
.> listA ++ tail(listB)
.> tail(tail(listA) ++ tail(listB))
Answer:
What does the following code do: .> listA = ['o', 'x', 'p', 'e']
.> 'r' : [head(listA)] ++ tail(tail(listA))
Answer:
|