Get Last Element of each list

19,771

Solution 1

Assuming this is about Common Lisp, there is a function last which returns a list containing the last item of a list. If you use this function with mapcan, which applies a given function to each element of a list and returns the concatenated results, you'll get what you want.

Note though that accessing the last element of a list is an O(N) operation, so if this isn't just homework after all, you might want to consider if you can't solve the real problem more efficiently than taking the last item of each list (maybe use another datastructure instead).

Solution 2

This, like most early LISPy homework problems is an exercise in thinking recursively and/or thinking in terms of induction. The way to start is to ask yourself simple questions that you can answer easily.

For example, if you had been asked to write something that gave you the first element in each list, I would thing about it this way:

Given a list of lists:

  1. What is first-element of every list in the list '()? (easy - null)
  2. What is first-element of every list in the list '(a)? (easy - a, or maybe an error)
  3. What is first-element of every list in the list '((a))? (easy - (a))
  4. What is first-element of any list in the form '(anything), where anything is a list? (easy - (first anything))
  5. What is the first element of every list in the form '(anything morestuff)? (easy - (cons (first anything) (first-element morestuff)) )
  6. What is first of an atom? either the atom or an error (depends on your point of view)
  7. What is first of null? nil.
  8. What is first of a list? (car list)

From here we can start writing code:

;; here's first, meeting questions 6-8
(define first (lambda (l)
  (cond 
    ((null? l) nil) ; Q7
    ((atom? l) l)   ; Q6
    (t (car l)))))  ; Q8

;; with first we can write first-element, meeting questions 1-5
(define first-element (lambda (l)
  (cond
    ((null? l) nil) ; Q1
    ((atom? l) (first l))   ; Q2
    (t (cons (first (car l) (first-element (cdr l)))))))) ; Q4-5

Now this isn't your homework (intentionally). You should play with this and understand how it works. Your next goal should be to find out how this differs from your assignment and how to get there.

With respect to MAPCAR? Don't worry about it. You need to learn how to solve recursive problems first. Then you can worry about MAPCAR. What is the point of this assignment? To help you learn to think in this mode. Dang near everything in LISP/Scheme is solved by thinking this way.

The reason I went with all the questions to break it down into the parts that I'm worried about. If I'm given the task "how do I do foo on every item in a list?" I should answer the questions: How do I do handle null? How do handle an atom? How do I do handle on the first element on the list? How do I handle everything else? Once I've answered that, then I figure out how to actually do foo. How do I do foo on null? How do I do foo on an atom? How do I do foo on a list?

Share:
19,771
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    Let us say I have a list ((3 4 5) (d e f) (h i j) (5 5 5 5))

    How can I get the last element of each list in such a way that the output would look like this (5 f j 5)?

  • Pete Kirkham
    Pete Kirkham over 14 years
    In common-lisp, the built-in functions LAST and MAPCAN may also be rather useful.
  • Admin
    Admin over 14 years
    Thanks for that answer but can you give me more information about that. like how MAPCAR is use. Sorry to ask but this just my firt attemp in developing in lisp hope you guys can help me more on this..Thanks in advance..btw, im using common lisp and sorry that i post my reply as answer.
  • sepp2k
    sepp2k over 14 years
    I've added links to the documentation for the mentioned functions. Those contain examples.
  • Admin
    Admin over 14 years
    Hi! i was able to make one the work some how the way i want.this is my code (defun lastelements(L) (if L (append (last (first L)) (lastelements(rest L))) ) ) But i have small problem..When i input '((4) (hello (world))) the ouput is something like this ((4) ((world))) but from example output give in our exercise it should look like this (4 (world))..Thanks in advance!
  • sepp2k
    sepp2k over 14 years
    Don't append, concatenate (last returns a list).
  • Eli Barzilay
    Eli Barzilay about 14 years
    Using mapcan is an extremely bad idea, especially for newbies.
  • ObieMD5
    ObieMD5 over 10 years
    I would expand your answer some more.
  • Victor
    Victor over 10 years
    I would like to see your improvement, or others. :)
  • Inaimathi
    Inaimathi over 10 years
    Have to agree with @EliBarzilay. In any project where I need mapcan, I end up defining a functional equivalent. It should really be named mapcan!, because it destructively modifies its list arguments.
  • Inaimathi
    Inaimathi over 10 years
    I'd do it without side-effects, and actually return the result rather than just printing it. Something like (defun lasts (list-of-lists) (loop for l in list-of-lists appending (last l)))
  • Inaimathi
    Inaimathi over 10 years
    A few comments: First, as a rule, don't put closing parens on separate lines; the indentation level on forms is enough to see the structure of the code and your editor should be balancing parens for you in any case. Second, code is typically written in lower case; the interpreter shouts back at you, but you don't need to do the same. Finally, I think your type signature should be SELECT-FROM-INNER-LIST :: [[a]] -> [a]; the return value isn't necessarily going to be a list of lists.