2024 年 Clojure 状态调查中分享您的想法!

欢迎!请查阅关于页面了解如何操作的更多信息。

0 投票
Clojure

您好,Clojurians,我对使用序列为数组填充最佳实践有疑问。

这不是一个 seq 结构。我指的是一个数学序列,例如,1, 2, 3, 4, 5, 6, 7, ..., n

我的背景是统计编程,因此生成数字列表非常常见且有用!

在 R 语言中,要生成一个数字数组,你会这样做

seq(1, 10) => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

或者缩写

1:10 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

这两种方法都被认为是惯用的,因为它们是可读的且运行速度快。

然后将数组分配给变量

nums = seq(1, 10)
nums => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

那么 Clojure 如何做这件事呢?

不幸的是,我找不到解决方案,因为任何包含“序列”的搜索都会不可避免地引导至 https://docs.clojure.org/clojure.core/seq

1 个答案

+1 投票

被选中
 
最佳答案

您应该使用范围

(range 10)
; => (0 1 2 3 4 5 6 7 8 9)
非常感谢!
为了完成回答,如果你想要在这个情况下有一个具有 O(1) 访问的索引化数据结构(持久性),你可以将`range`的结果存入一个向量

(vec (range 10))

或者,如果你想要一个真正的可变数组,

(long-array (range 10))

向量是典型的“持久数组列表”。如果你的操作涉及大量的随机访问或更新,那么向量在实践中的性能将远远超过序列,因为序列获取第 n 个元素(列表性能)是 O(n),并且它们不像向量那样支持自带的更新操作,如`assoc`。

从数学的角度来看, "这不是一个 seq 结构。我指的是数学序列,例如,1, 2, 3, 4, 5, 6, 7, ..., n 在 clojure 中相当没有意义,因为所有集合或可迭代的都是可序列的。你,例如,可以简单地处理无限序列,并且只遍历或消耗计算所需要的部分。以这种方式定义算法是常见的(生成所有可能解决方案的无限序列,然后过滤该序列,从中取出,删除元素,映射到它,等等,直到找到结果)。你还可以定义生成函数(例如通过`iterate`或较低的`lazy-seq`级别的实现)。在 https://clojure.github.io/math.combinatorics/  中有很多有趣的例子。
虽然原始答案已经足够,但我已经不时使用 (vec (range ...)),原因是你描述的原因。

如果我为 ask.clojure.org 启用了邮件更新,我就会看到你的评论,可能避免了些麻烦。我现在会这样做!

再次感谢。
...