最後の関数を使わずに最後の要素を見つける

私はclojureを学んでおり、より良くなるために 4clojure.com を使っています。私はちょうど#19 を完成しましたが、作者が持っているように私はそれをやっていないかもしれません予期された - 私はおそらく何とかポイントを逃したように。

4 clojure problem 19

最後の関数を使用できませんという制約がある場合、これは妥当な解決策のようですか?

#(.get %(- (count %) 1))
22
もしあなたが気分が良くなったら、 nth を使ったこと以外はまったく同じことをしました。 4clojure は素晴らしいです!
追加された 著者 Droogans,
IMHOこのアプローチは、制限を回避するだけですが、実際には学習課題としては受け入れられません。関数型プログラミングの学習は、一般的な問題解決と考え方の新しい方法を学ぶことです。 object something = list.get(n-1); はそうではありませんか? @Alex Taggartの答えを見ることをお勧めします。
追加された 著者 evictednoise,

8 答え

あなたが使うつもりなら:

#(first (reverse %))

あなたは "comp"で関数を作成することもできます:

(comp first reverse)

これはおそらくもっと慣用的で読みやすくなります。怠惰ではない "逆"についての同じ警告がここに当てはまります。

39
追加された
彼らは[長さ1]の奇妙なものではなく、
追加された 著者 Nik,
これも私が思いついたものです。これは最高の答えです。
追加された 著者 Banjocat,

それは有効な解決策です。私は#(nth%(dec(count%)))をもっと慣れ親しんでいると思いますが、機能的には同等です。

26
追加された
@devdankeこのケースでは、Clojureに dec 関数があることは、デクリメントが強いヒントであるという事実です。
追加された 著者 nha,
なぜそれがもっと「慣用的」なのかを教えてください。それはClojure学生に役立つでしょう:-)
追加された 著者 devdanke,

どうですか

reduce (fn [a b] b)

ブランク

21
追加された

カウントに依存しない純粋に再帰的なアプローチは次のとおりです。

(defn end [[n & more]]
  (if more
    (recur more)
    n))
18
追加された
これは4clojureのWebサイトで許容される解決策ではありません
追加された 著者 magnetar,
もちろん、これはシーケンスの最後の要素を返す end という関数を定義しています。あなたが探しているものは次のとおりです:(fn [[n&more]](もしあればmore(recur more)))
追加された 著者 ag0rex,

うん、それは合理的な解決策です。しかし、いくつかのこと:

  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 %))

7
追加された
@mange: rseq という関数があり、その逆の順序でコレクションにアクセスするだけです。もちろん、コレクションはランダムアクセスとベクトルのような有限でなければなりません。
追加された 著者 Goran Jovic,
Ha、私は#3のソリューションが気に入っていますが、これは不正行為のようです。
追加された 著者 javamonkey79,
公正では、 count/nth ソリューションは、 reverse ソリューションと同じように怠惰ではありません。そして悲しいことに、怠惰なシーケンスの怠惰な逆行は不可能です。
追加された 著者 amalloy,
@mangeはい、逆は怠惰ではありません。怠惰な逆を作り、このイディオムを使うことは涼しいでしょう。
追加された 著者 ivant,
私は怠惰を話していません。 reverse は構造体を複製します(ランダムアクセスのベクトルの場合はもっと知的かもしれませんが、リスト/任意のseqでは使用できません)。メモリに収まるものであれば、 count / nth 解決策は失敗しません。
追加された 著者 mange,
seqが本当に大きかったら、 reverse は(メモリ内のシーケンスを複製するので)それほど大きくないでしょうが、これはちょっとした問題ではありません。また、 nth .get よりも慣れています。
追加された 著者 mange,

私は、(comp peek vec)のようなものでもっと簡単になると思います。問題は、 last はシーケンスで作業しており、ドキュメンテーションのように線形時間で動作するということです。

clojure.core/last([coll])collの最後のアイテムをリニアに返します   時間

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

clojure.core/peek([coll])リストまたはキューの場合、最初と同じ、a   ベクトルと同じですが、より効率的です。もし   コレクションは空であり、nilを返します。

2
追加された
素晴らしい洞察力、ありがとう!
追加された 著者 Adam Arold,
@誰かdownvoted:説明する気に?
追加された 著者 Adam Arold,
リストをベクトルに変換すると、線形時間がかかり、メモリが割り当てられます。科学を行うことで(数字を3回使用して数字を打ち込む)、私はvec-and-peekが最後より遅いと結論づけました。もしあなたが同じリスト()をたくさんするつもりならば、それはベクトルを前のベクトルに変換するために支払うかもしれません。なぜなら、θで1つの(vec) θ(n)とθ(n)との差はθ(n)であり、θ(n)のn (last)はθ(n)である。また、読みやすいコードを書くためにさまざまな方法で払うかもしれません;-)
追加された 著者 Jonas Kölker,

私のソリューションは誰よりも優れているとは思わないが、同じ問題を解決する別の方法だと思う:

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

これは fn を使用しています。

1
追加された
(fn getLast [l] (if (= (count l) 1) (first l) (getLast (rest l))) )
1
追加された
あなたの答えを教えてもらえますか?コードのみの回答は質問に答えるかもしれませんが、なぜあなたがこれをしたのかを人々に教えていません。
追加された 著者 Machavity,