3

I am trying to find the smallest element in a list of numbers.

This is trivial when using explicit recursion, but I am looking for a way to do this using solely the built-in higher-order functions, like

map,

filter,

and foldr.

In other words, I want to use a combination of these functions to get what I am looking for.

Swifty
  • 839
  • 2
  • 15
  • 40
  • Not overly familiar with scheme but could you repeatedly filter all elements smaller than the first one in the list until the list size is one? – gowrath Dec 05 '16 at 00:31

3 Answers3

1

Use foldr. The accumulator begins as +inf.0. The combine-accumulator-and-element should return the smallest of the accumulator and the element.

soegaard
  • 30,661
  • 4
  • 57
  • 106
  • Curious why you recommend foldl instead of foldr? What difference would there be compared to using foldl? – Mulan Dec 05 '16 at 06:23
  • I just picked the same fold as mentioned in the question. You are right: foldl would be better in this case, since `min` doesn't depend on the order of arguments. – soegaard Dec 05 '16 at 09:22
  • wups I didn't mean to suggest `foldl` was better. I honestly don't know when it's better to use one over the other when they both result in the same return value – Mulan Dec 05 '16 at 09:24
  • For small lists it doesn't matter which one is used. If you look at the definitions of `foldl` and `foldr` you will see that the first can begin using the function right away while the other must wait until it reached the end of list before it can use the function "on the way back". – soegaard Dec 05 '16 at 09:28
1

I am trying to find the smallest element in a list of numbers.

The obvious way is to use the built-in min

#lang racket

(apply min '(5 2 3 6 4 0 9 -3 2 6))
;; => -3

However, if you have to implement your own min procedure, foldl will help you. I also made this procedure throw an error when attempting to use it on an empty list – much like the built-in min would do if you tried applying it to zero arguments.

#lang racket

(define (min xs)
  (match xs
    ((list x xs ...) (foldl (λ (x acc) (if (< x acc) x acc))
                            x
                            xs))
    (_ (error 'min "must use non-empty list"))))


(min '(5 2 3 6 4 0 9 -3 2 6))
;; => -3

(min '())
;; => min: must use non-empty list
Mulan
  • 129,518
  • 31
  • 228
  • 259
0

One can also use 'sort' function on the list and then take first element of the sorted list:

(first (sort '(5 2 3 6 4 0 9 -3 2 6) <))
;; => -3
rnso
  • 23,686
  • 25
  • 112
  • 234