user6911980
user6911980

Reputation:

Second to last item in a list in F#

This is what my initial thought was and there were no issues until it was called; What is wrong with this exactly?

let SecLastItem myList=  
    List.rev myList
        |>printfn myList.[1]

How do I rectify the problem here? What is the best way to find the 2nd to last item of a list?

Upvotes: 1

Views: 711

Answers (3)

hocho
hocho

Reputation: 1749

What is the best way to find the 2nd to last item of a list?

If you do not want to reverse the list, you can use pattern matching and return an option if the list is not long enough for a 'second to last item'. Something like this.

let rec secondToLast ls = 
    match ls with 
    |   []              -> None
    |   h :: ht :: []   -> Some(h)
    |   h :: t          -> secondToLast t

test with

printfn "%A" (secondToLast [1; 2; 3; 4])

Upvotes: 5

Sehnsucht
Sehnsucht

Reputation: 5049

printfn expects a format first printfn "%A" arg

But there is more, functional programming favors immutability so List.rev returns a new list without modifying mylist
So printing the second item in myList won't give the second to last just the second from start (if it exists otherwise it'll crash)

That said you should separate function doing something and logging/printing that' better for reuse and composability.

// trySecLastItem : 'a list -> 'a option
let trySecLastItem = List.rev >> List.tryItem 2

// usage
printfn "%d" (trySecLastItem someList) // ex Some 42 or None

Now as trySecLastItem returns an option you have to take care of that (using defaultArg for example)

// maybeSecLast : int option
let maybeSecLast = trySecLastItem someList
printfn "%d" (defaultArg maybeSecLast 42)

Upvotes: 5

Ringil
Ringil

Reputation: 6537

You need to have a formatter with printfn

let SecLastItem myList=  
    let revList = List.rev myList
    printfn "%A" revList.[1]

Upvotes: 3

Related Questions