gpt4 book ai didi

list - 关联或更新 Clojure 列表和惰性序列

转载 作者:行者123 更新时间:2023-12-01 02:31:31 25 4
gpt4 key购买 nike

如果我有一个向量(def v [1 2 3]),我可以用(assoc v 0 666)替换第一个元素,得到 [666 2 3]

但如果我在映射向量后尝试做同样的事情:

(def v (map inc [1 2 3]))
(assoc v 0 666)

抛出以下异常:

ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.Associative

编辑或更新惰性序列的单个元素最惯用的方法是什么?

我应该使用 map-indexed 并仅更改索引 0 还是将惰性序列实现为向量,然后通过 assoc/update 对其进行编辑?第一个有保持惰性的优点,而第二个效率较低但可能更明显。

我想对于第一个元素,我也可以使用 drop 和 cons。还有其他方法吗?我无法在任何地方找到任何示例。

最佳答案

What's the most idiomatic way of editing or updating a single element of a lazy sequence?

没有用于修改序列/列表的单个元素的 内置 函数,但 map-indexed 可能是最接近的东西。这不是列表的有效操作。假设您不需要 懒惰,我会将序列倒入向量中,这就是 mapv 所做的,即 (into [] (map f coll) )。根据您使用修改后序列的方式,对其进行矢量化和修改可能同样高效。

您可以使用 map-indexed 编写一个函数来执行类似的懒惰操作:

(defn assoc-seq [s i v]
(map-indexed (fn [j x] (if (= i j) v x)) s))

或者,如果您想在不进行矢量化的情况下一次性完成这项工作,您也可以使用换能器:

(sequence
(comp
(map inc)
(map-indexed (fn [j x] (if (= 0 j) 666 x))))
[1 2 3])

实现您的用例是只修改惰性序列中的第一项,然后您可以在保持惰性的同时做一些更简单的事情:

(concat [666] (rest s))

更新回复:关于优化的评论:当更新 1,000,000 个元素的惰性序列中的第 500,000 个元素时,leetwinski 的 assoc-at 函数快了约 8 毫秒,所以如果你正在寻找,你应该使用他的答案从本质上低效的操作中榨取每一点性能:

(def big-lazy (range 1e6))

(crit/bench
(last (assoc-at big-lazy 500000 666)))
Evaluation count : 1080 in 60 samples of 18 calls.
Execution time mean : 51.567317 ms
Execution time std-deviation : 4.947684 ms
Execution time lower quantile : 47.038877 ms ( 2.5%)
Execution time upper quantile : 65.604790 ms (97.5%)
Overhead used : 1.662189 ns

Found 6 outliers in 60 samples (10.0000 %)
low-severe 4 (6.6667 %)
low-mild 2 (3.3333 %)
Variance from outliers : 68.6139 % Variance is severely inflated by outliers
=> nil

(crit/bench
(last (assoc-seq big-lazy 500000 666)))
Evaluation count : 1140 in 60 samples of 19 calls.
Execution time mean : 59.553335 ms
Execution time std-deviation : 4.507430 ms
Execution time lower quantile : 54.450115 ms ( 2.5%)
Execution time upper quantile : 69.288104 ms (97.5%)
Overhead used : 1.662189 ns

Found 4 outliers in 60 samples (6.6667 %)
low-severe 4 (6.6667 %)
Variance from outliers : 56.7865 % Variance is severely inflated by outliers
=> nil

assoc-at 版本在更新大型惰性序列中的 first 项时快 2-3 倍,但并不比 (last (concat [666](休息大懒惰)))

关于list - 关联或更新 Clojure 列表和惰性序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49423947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com