droptake

此页面描述了集合管道模式中的一个操作。有关更多上下文,请阅读

切片

返回列表中给定第一个和最后一个位置之间的子序列。

如果你想要列表的一部分,你可以取列表的切片。根据你想要的切片,不同的语言提供了不同的运算符。

最通用的形式允许你切出任何范围的元素。

ruby…
[1,2,3,4,5,6].slice(2..4)
# => [3, 4, 5]
clojure…
(subvec [1 2 3 4 5 6] 2 5)
;; => [3 4 5]

这两个基本示例提出了一些要点。首先,大多数语言使用从零开始的索引,因为程序员自然地通过说“0,1,2… 9”来数到十。

Ruby 使用包含范围指定切片,而 clojure 使用两个数字,开始包含,结束排除。Ruby 的范围表示法允许使用以下方法排除结束

ruby…
[1,2,3,4,5,6].slice(2...5)
# => [3, 4, 5]

我很少使用三点形式,一些程序员不喜欢使用它,因为“...”和“..”之间的区别非常微妙。

Ruby 可以使用数组参数进行切片。

ruby…
[1,2,3,4,5,6][2..4]
# => [3, 4, 5]

这种形式在管道形式中可能读起来不太好。

Clojure 的 subvec 函数只适用于向量,而不适用于一般的列表。它在向量上很快(因为它们是索引的),但在 clojure 列表的其他形式上不会很快,因此它对操作向量的限制有助于避免性能意外,而牺牲了操作使用的一般性。Subvec 也不符合 clojure 管道的约定,因为集合参数不是最后一个参数,所以它不适用于 ->>

在 clojure 中,你可以省略第二个参数,从第一个切片到列表的末尾,在 ruby 中,你可以使用范围上的负数来做到这一点。

ruby…
[1,2,3,4,5,6].slice(2..-1)
# => [3, 4, 5, 6]
clojure…
(subvec [1 2 3 4 5 6] 2)
;; => [3 4 5 6]

Ruby 的范围可以有负参数,从列表的末尾开始计数。

ruby…
[1,2,3,4,5,6].slice(-4..-2)
# => [3, 4, 5]

许多语言更喜欢使用单独的 take 和 drop 函数,而不是使用通用的切片操作。Take 返回第一个元素(相当于 ruby 中的 slice(0..2))。

ruby…
[1,2,3,4,5,6].take(3)
# => [1, 2, 3]
clojure…
(take 3 [1 2 3 4 5 6])
;; => (1 2 3)

Drop 丢弃第一个元素(ruby 中的 slice(-3..-1))。

ruby…
[1,2,3,4,5,6].drop(3)
# => [4, 5, 6]
clojure…
(drop 3 [1 2 3 4 5 6])
;; => (4 5 6)

你可以通过管道连接 take 和 drop 来形成切片。

ruby…
[1,2,3,4,5,6].take(5).drop(2)
# => [3, 4, 5]
clojure…
(drop 2 (take 5 [1 2 3 4 5 6]))
;; => (3 4 5)

请注意,这些数字对应于 ruby 切片运算符中的排他范围。

take-drop 方法适用于惰性列表,因为这两个操作都可以在不解析整个列表的情况下完成。

如果你需要从列表的末尾开始工作,clojure 提供了 take-lastdrop-last

clojure…
(take-last 2 [1 2 3 4 5 6])
;; => (5 6)
(drop-last 2 [1 2 3 4 5 6])
;; => (1 2 3 4)