26

Python には、「スライス」と呼ばれるリストの一部を取得する便利な方法があります。

a = [1,2,3,4,5,6,7,8,9,10] # ≡ a = range(1,10)
a[:3] # get first 3 elements
a[3:] # get all elements except the first 3
a[:-3] # get all elements except the last 3
a[-3:] # get last 3 elements
a[3:7] # get 4 elements starting from 3rd (≡ from 3rd to 7th exclusive)
a[3:-3] # get all elements except the first 3 and the last 3

Clojure で遊んclojure.repl/docでみると、それらすべてに相当するものが見つかりましたが、それらが慣用的なものかどうかはわかりません。

(def a (take 10 (iterate inc 1)))
(take 3 a)
(drop 3 a)
(take (- (count a) 3) a)
(drop (- (count a) 3) a)
(drop 3 (take 7 a))
(drop 3 (take (- (count a) 3) a))

私の質問は、Clojure でシーケンスをスライスする方法ですか? 言い換えれば、シーケンスのさまざまな部分を返す正しい方法は何ですか?

4

4 に答える 4

35

orを代わりに使用countして、すべてのものを単純化できます。take-lastdrop-last

(def a (take 10 (iterate inc 1)))
(take 3 a) ; get first 3 elements
(drop 3 a) ; get all elements except the first 3
(drop-last 3 a) ; get all elements except the last 3
(take-last 3 a) ; get last 3 elements
(drop 3 (take 7 a)) ; get 4 elements starting from 3
(drop 3 (drop-last 3 a)) ; get all elements except the first and the last 3

また、以下のコメントで提案されているように、->>マクロを使用して複数の操作を「スレッド化」できます。たとえば、最後の 2 行は次のように書くこともできます。

(->> a (take 7) (drop 3)) ; get 4 elements starting from 3
(->> a (drop-last 3) (drop 3)) ; get all elements except the first and the last 3

リストに 2 つの操作を適用するだけの場合、2 つのメソッドはどちらも非常に読みやすいと思いますがtakemapfilter、 のような長い文字列がある場合drop、マクロをfirst使用->>するとコードがはるかに読みやすくなり、おそらくさらに簡単になります。書きます。

于 2012-08-22T09:24:24.577 に答える
25

Python のシーケンスの概念は、Clojure のものとは大きく異なります。

パイソンでは、

  • シーケンスは、非負の数でインデックス付けされた有限順序セットです。と
  • リストは、スライスを追加または削除できる可変シーケンスです。

クロジュアでは、

  • シーケンスは、firstrest、および をサポートするインターフェイスconsです。
  • リストは、要素を追加 (または削除) する (consまたは )不変の順次コレクションです (とにかく、そのように変更されたリストを返します)。restfirst

Clojure で Python のリストに最も近いものはvectorです。Adam Sznajder が示唆しているようsubvec、Python のようにスライスを追加または削除することはできませんが、を使用してスライスできます。

subvec高速な一定時間の操作dropですが、バイパスされた要素の数に対して料金がかかりtakeます(トラバースする要素に対して料金がかかりますが、これらはあなたが興味を持っているものです)。

あなたの例は...

(def a (vec (range 1 (inc 10))))

(subvec a 0 3)
; [1 2 3]

(subvec a 3)
; [4 5 6 7 8 9 10]

(subvec a 0 (- (count a) 3))
; [1 2 3 4 5 6 7]

(subvec a (- (count a) 3))
; [8 9 10]

(subvec a 3 (+ 3 4))
; [4 5 6 7]

(subvec a 3 (- (count a) 3))
; [4 5 6 7]
于 2014-06-07T08:41:41.333 に答える
11

機能がありますsubvec。残念ながら、これはベクトルでしか機能しないため、シーケンスを変換する必要があります。

http://clojuredocs.org/clojure_core/clojure.core/subvec

于 2012-08-22T09:27:25.523 に答える
5

シーケンスのスライスは、少し「コード臭」があります。一般に、シーケンスはアイテムのシーケンシャル アクセス用に設計されています。

多くのスライシング/連結を行う場合は、より優れたデータ構造を利用できます。特に、RRB-Tree ベクターの実装を確認してください。

これにより、非常に効率的な運用がサポートsubvecされcatvecます。

于 2014-08-14T04:56:57.427 に答える