请在 2024 Clojure 状态调查! 分享您的想法。

欢迎!请查看 关于 页面了解更多此论坛的详细信息。

0
序列

Range 以结束参数作为排他。

> (range 1 3)
(1 2)

我希望有一个类似于 range 但包含结束状态的函数。

> (inclusive-range 1 3)
(1 2 3)

不幸的是,这并不等同于将结束状态添加到 range 返回的 seq 中。

> (inclusive-range 1 2.5)
(1 2)

我相信 Clojure 中没有提供直接实现这个功能的方法,但我找到了一个有用的小技巧。我已经写了一个功能(虽然不是懒惰的)。

(defn inclusive-range
  "Return a sequence of nums from START to END, both inclusive, by STEP."
  ([start end]
   (inclusive-range start end 1))
  ([start end step]
   (let [test-for-done (if (< start end)
                         >
                         <)]
     (if (test-for-done start (+ start step))
       []
       (loop [nums []
              cur start]
         (if (test-for-done cur end)
           nums
           (recur (conj nums cur)
                  (+ cur step))))))))

我是不是错过了更好的方法?这是否可以添加到 Clojure 中?

2个答案

+1

我通常需要这样的功能,所以写了 "thru" 函数

`
tupelo.core/thru

(thru end)
(thru start end)
(thru start end step)

返回一个数字序列。类似于 clojure.core/rng,但包含右侧边界值。不是懒惰的。
`

0

有一个快速的想法,尽管我不完全确定我理解了您的要求/想法

> (defn inclusive-end-range 
    [start end]
    (range start (inc end)))
#'inclusive-end-range
> (inclusive-end-range 1 3)
(1 2 3)
OP特别提到了那个情况

不幸的是,这并不等同于将结束状态添加到 range 返回的 seq 中。

> (inclusive-range 1 2.5)
(1 2)

(range 1 (inc 2.5)) => (1 2 3)。
这看起来应该由`floor`来处理,所以`#(range %1 (inc (Math/floor %2)))`。当增加步长参数时,情况会更加复杂,但是仍然是可实现的,并且比原始基于`loop`的解决方案简单。
Sean,你说得对 - 我误解了这一点。感谢你的澄清,我为造成的混乱道歉。
我本想写一个回答,但意识到我做不到,因为问题提得不明确,这个讨论显示了原因。当你开始为`end`使用分数值时,谈论“包含结束”就变得没有意义了。示例 `(inclusive-range 1 2.5)` 明显不包括结束,甚至在原始问题中也是如此。因此,如果可以精确地指定函数的期望行为,通过将参数转换并传递给 `range` 来实现它将非常简单。正如尤金·帕霍莫夫提到的,这可能涉及将步长值加到 `end` 上,并对结果使用 `floor` 来推导传递给 `range` 的 `end` 值。
...