Question

I'm using scheme R5RS.

Given a list with multiple entries, I would like to return that list up until the last occurrence of a given element.

So for the following input:

A list '("hi" "how" "are" "you")
Keyword "you"

I want the following output:
A list '("hi" "how" "are")

I couldn't find a function in scheme R5RS with this capability but maybe I am missing something. If such a function doesn't exist, how would I implement it?

Was it helpful?

Solution

It's a little trickier than it seems at first sight, but this should work:

(define (last lst key)
  (cond ((null? lst) '())
        ((member key (cdr lst))
         (cons (car lst) (last (cdr lst) key)))
        (else '())))

The key insight is that you should use member to check if the element is still present in the list (that will tell us when we've found its last occurrence). Also you should consider two special cases - what happens if the list is empty, or if the key is not in the list? In both cases I'm returning an empty list. For example:

(last '("hi" "how" "are" "you") "you")
=> '("hi" "how" "are")

(last '("hi" "how" "are" "how" "you") "how")
=> '("hi" "how" "are")

(last '("hi" "how" "are" "how" "you") "today")
=> '()

(last '() "empty")
=> '()

OTHER TIPS

This can be done quite succintly if you reverse the list and then look for the first occurence:

(define (last lst key)
  (define r (member key (reverse lst)))
  (if r 
      (reverse (cdr r))
      '()))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top