2024 年 Clojure 状态调查! 中分享您的观点。

欢迎!请参阅 关于 页面以了解更多关于如何使用本站的信息。

0
Clojure

大家好,我有一个问题关于如何以数值序列的方式填充数组的最优实践。

这并非是一个序列结构。在这里我是一个指数学上的序列,例如 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)函数。

(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)(列表性能),而它们不支持像向量那样的更新操作。

从数学的角度来看,“这不是一个序列结构。我指的是数学序列,例如,1, 2, 3, 4, 5, 6, 7, ..., n”在Clojure中相当没有意义,因为所有的集合或迭代器都是可序列的。你可以简单地处理无限序列,并且只遍历或消费计算所需的那么多的部分。通常以这种方式定义算法(生成所有可能的解的可能无限序列,然后过滤该序列,从中选取,删除项目,映射到它,等等,直到找到结果)。你还可以定义生成函数(例如,通过`iterate`或使用`lazy-seq`等低级实现)。有关更多信息,请参阅https://clojure.github.io/math.combinatorics/
虽然原始答案已经足够好,但自从我询问这个问题以来,我有时会使用(vec (range ...)),原因是你所描述的。

如果我启用了ask.clojure.org的电子邮件更新,我就能看到你的评论,可能就会少一些麻烦。我现在就做。

再次感谢。
...