list 在 Clojure 中,我什么时候应该在列表上使用向量,反之亦然?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1147975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In Clojure, when should I use a vector over a list, and the other way around?
提问by Rayne
I read that Vectors are not seqs, but Lists are. I'm not sure what the rationale is for using one over the other. It seems that vectors are used the most, but is there a reason for that?
我读到 Vectors 不是 seqs,但 Lists 是。我不确定使用一个而不是另一个的理由是什么。似乎向量被使用得最多,但有什么原因吗?
采纳答案by Rayne
Once again, it seems I've answered my own question by getting impatient and asking it in #clojure on Freenode. Good thing answering your own questions is encouraged on Stackoverflow.com :D
再一次,我似乎已经不耐烦地回答了我自己的问题,并在 Freenode 上的 #clojure 中提问。鼓励在 Stackoverflow.com 上回答您自己的问题是件好事:D
I had a quick discussion with Rich Hickey, and here is the gist of it.
我与 Rich Hickey 进行了一次快速讨论,这是它的要点。
[12:21] <Raynes> Vectors aren't seqs, right?
[12:21] <rhickey> Raynes: no, but they are sequential
[12:21] <rhickey> ,(sequential? [1 2 3])
[12:21] <clojurebot> true
[12:22] <Raynes> When would you want to use a list over a vector?
[12:22] <rhickey> when generating code, when generating back-to-front
[12:23] <rhickey> not too often in Clojure
回答by Chris Jester-Young
If you've done Java programming a lot, and are familiar with the Java collection framework, think of lists like LinkedList
, and vectors like ArrayList
. So you can pretty much choose containers the same way.
如果您经常进行 Java 编程,并且熟悉 Java 集合框架,请考虑像 的列表LinkedList
和像 的向量ArrayList
。所以你几乎可以用同样的方式选择容器。
For further clarification: if you intend to add items individually to the front or the back of the sequence a lot, a linked list is much better than a vector, because the items don't need to be shuffled around each time. However, if you want to get at specific elements (not near the front or back of the list) frequently (i.e., random access), you will want to use vector.
进一步澄清:如果您打算将项目单独添加到序列的前面或后面很多,链表比向量要好得多,因为项目不需要每次都被打乱。但是,如果您想频繁地(即随机访问)获取特定元素(不在列表的前面或后面附近),您将需要使用向量。
By the way, vectors can easily be turned into seqs.
顺便说一下,向量可以很容易地变成序列。
user=> (def v (vector 1 2 3))
#'user/v
user=> v
[1 2 3]
user=> (seq v)
(1 2 3)
user=> (rseq v)
(3 2 1)
回答by Svante
Vectors have O(1) random access times, but they have to be preallocated. Lists can be dynamically extended, but accessing a random element is O(n).
向量有 O(1) 次随机访问时间,但它们必须预先分配。列表可以动态扩展,但访问随机元素是 O(n)。
回答by mikera
When to use a vector:
何时使用向量:
- Indexed access performance - You get ~O(1) cost for indexed access vs. O(n) for lists
- Appending - with conj is ~O(1)
- Convenient notation - I find it both easier to type and to read [1 2 3] than '(1 2 3) for a literal list in circumstances where either would work.
- 索引访问性能 - 索引访问的成本约为 O(1),而列表的成本为 O(n)
- 附加 - 与 conj 是 ~O(1)
- 方便的符号 - 我发现 [1 2 3] 比 '(1 2 3) 更容易输入和阅读,在两种情况下都可以工作。
When to use a list:
何时使用列表:
- When you want to access it as a sequence (since lists directly support seq without having to allocate new objects)
- Prepending - adding to the start of a list with cons or preferably conj is O(1)
- 当你想作为一个序列访问它时(因为列表直接支持 seq 而不必分配新对象)
- 前置 - 添加到带有 cons 或最好 conj 的列表的开头是 O(1)
回答by Arthur Ulfeldt
just a quick side note:
只是一个快速的旁注:
"I read that Vectors are not seqs, but Lists are."
sequences are more generic than either lists or vectors (or maps or sets).
Its unfortunate that the REPL prints lists and sequences the samebecause it really makes it look like lists are sequences even though they are different. the (seq ) function will make a sequence from a lot of different things including lists, and you can then feed that seq to any of the plethora of functions that do nifty things with seqs.
序列比列表或向量(或映射或集合)更通用。
不幸的是,REPL 打印列表和序列是一样的,因为它确实让列表看起来像是序列,即使它们不同。(seq) 函数将从许多不同的事物(包括列表)中生成一个序列,然后您可以将该 seq 提供给任何使用 seqs 做漂亮事情的函数。
user> (class (list 1 2 3))
clojure.lang.PersistentList
user> (class (seq (list 1 2 3)))
clojure.lang.PersistentList
user> (class (seq [1 2 3]))
clojure.lang.PersistentVector$ChunkedSeq
Sec has a shortcut that returns its argument if it is already a seq:
Sec 有一个快捷方式,如果它已经是一个 seq 则返回它的参数:
user> (let [alist (list 1 2 3)] (identical? alist (seq alist)))
true
user> (identical? (list 1 2 3) (seq (list 1 2 3)))
false
static public ISeq seq(Object coll){
if(coll instanceof ASeq)
return (ASeq) coll;
else if(coll instanceof LazySeq)
return ((LazySeq) coll).seq();
else
return seqFrom(coll);
}
lists are sequences, though other things are as well, and not all sequences are lists.
列表是序列,但其他事物也是如此,并非所有序列都是列表。