Get Last Element of each list
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:
- What is first-element of every list in the list
'()
? (easy -null
) - What is first-element of every list in the list
'(a)
? (easy -a
, or maybe an error) - What is first-element of every list in the list
'((a))
? (easy -(a)
) - What is first-element of any list in the form
'(anything)
, where anything is a list? (easy -(first anything)
) - What is the first element of every list in the form
'(anything morestuff)
? (easy -(cons (first anything) (first-element morestuff))
) - What is first of an atom? either the atom or an error (depends on your point of view)
- What is first of null?
nil
. - 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?
Admin
Updated on June 04, 2022Comments
-
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 over 14 yearsIn common-lisp, the built-in functions LAST and MAPCAN may also be rather useful.
-
Admin over 14 yearsThanks 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 over 14 yearsI've added links to the documentation for the mentioned functions. Those contain examples.
-
Admin over 14 yearsHi! 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 over 14 yearsDon't append, concatenate (
last
returns a list). -
Eli Barzilay about 14 yearsUsing
mapcan
is an extremely bad idea, especially for newbies. -
ObieMD5 over 10 yearsI would expand your answer some more.
-
Victor over 10 yearsI would like to see your improvement, or others. :)
-
Inaimathi over 10 yearsHave to agree with @EliBarzilay. In any project where I need
mapcan
, I end up defining a functional equivalent. It should really be namedmapcan!
, because it destructively modifies its list arguments. -
Inaimathi over 10 yearsI'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 over 10 yearsA 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.