javamonkey79
javamonkey79

Reputation: 17775

clojure find last element without using last function

I'm learning clojure and have been using 4clojure.com to get better. I just completed #19 but it seems like maybe I haven't done it quite as the author's have anticipated - like I've perhaps missed the point somehow.

4 clojure problem 19

Given the constraint that you cannot use the last function does this seem like a reasonable solution?

#(.get %(- (count %) 1))

Upvotes: 31

Views: 14503

Answers (8)

Dragos Sava
Dragos Sava

Reputation: 11

(fn getLast [l] (if (= (count l) 1) (first l) (getLast (rest l))) )

Upvotes: 0

Coding Enthusiast
Coding Enthusiast

Reputation: 3933

I don't think my solution is better than anyone else but I think it is another way of solving the same problem:

(fn 
  [x] 
  (nth x (- (count x) 1)))

This is using the fn.

Upvotes: 2

Adam Arold
Adam Arold

Reputation: 30538

I think you can get even simpler with something like (comp peek vec). I think the problem is that last is working with sequences and works in linear time as the documentation says:

clojure.core/last ([coll]) Return the last item in coll, in linear time

peek on the other hand is faster than last according to the docs:

clojure.core/peek ([coll]) For a list or queue, same as first, for a vector, same as, but much more efficient than, last. If the collection is empty, returns nil.

Upvotes: 1

mudphone
mudphone

Reputation: 946

If you're going to use:

#(first (reverse %))

You might as well compose the function with "comp":

(comp first reverse)

This is probably a little more idiomatic and easier to read. The same caveat about "reverse" not being lazy applies here.

Upvotes: 43

Ankur
Ankur

Reputation: 33637

What about

reduce (fn [a b] b)

In the blank

Upvotes: 23

Alex Taggart
Alex Taggart

Reputation: 7825

Here's a purely recursive approach that doesn't rely on counting:

(defn end [[n & more]]
  (if more
    (recur more)
    n))

Upvotes: 20

Sean Nilan
Sean Nilan

Reputation: 1745

Yeah that's a reasonable solution. A few things though:

  1. It's more idiomatic to use the function dec instead of subtracting by one.

    #(.get % (dec (count %)))

  2. Follow other people on 4clojure. That way you can see their solutions to the problem after you solve it. I'm working through 4clojure myself and find it very useful to learn about the language, especially certain idioms.

  3. The first solution I thought of would just be to reverse the list and take the first element.

    #(first (reverse %))

Upvotes: 8

mange
mange

Reputation: 3212

That's a valid solution. I would go with #(nth % (dec (count %))) as being more idiomatic, but they're functionally equivalent.

Upvotes: 32

Related Questions