在Clojure中,我希望将列表中的特定项(列表)与其他项进行更改。这是我的结构:
(def myLis '((3 3) (5 5) (5 5)))
(def som '(4 4))我希望用myLis更改som中的第二个元素。结果在myLis中是'((3 3) (4 4) (5 5)),这是基本的例子。我在myList里有几百种商品。我尝试assoc和更新-in,但这不能在列表上工作。
当我尝试使用assoc并更新:
(update-in myLis [1] som)
(assoc myLis 1 som)
(assoc-in myLis [1] som)犯了这样的错误:
clojure.lang.PersistentList cannot be cast to clojure.lang.Associative如何快速更改此结构中的第n个元素(列表列表)。
发布于 2016-11-02 09:33:14
正如克洛尔圣经(Clojure程序设计)中所指出的:
因为列表是链表,所以它们不支持有效的随机访问;因此,列表上的nth将以线性时间运行(与与向量、数组等一起使用的恒定时间相反),而且get根本不支持列表,因为这样做不符合get的次线性效率目标。
因此,为了替换列表中的元素,您必须遍历所有元素,从而在列表中运行的时间越长,并使用列表前面的元素、新项和之后的所有元素(rest)重新构建列表。或者,将列表转换为向量,如果您必须使用列表,则使用update-in并将其返回到列表中。
但是,如果可以的话,您是否可以在代码中使用序列而不是列表,这是值得的,因此您可以互换地使用向量或其他更有效地处理它们的抽象。
但是,通过列表满足基本需求的一个简单函数是:
(defn list-update-in [l i x]
(let [newlist (take i l)
newlist (concat newlist (list x))
newlist (concat newlist (drop (+ 1 i) l))]
newlist))
user> (list-update-in '((1 2) (2 3) (3 4)) 1 '(8 9))
((1 2) (8 9) (3 4))对此没有越界检查
发布于 2016-11-02 04:04:06
在大多数情况下,您通常应该优先使用像[1 2 3]这样的向量,而不是像'(1 2 3)这样的列表。在Clojure中,list通常用于函数调用(如(+ 1 2) ),而用于数据文字向量(通常用于[1 2 3] )。
下面的代码显示了两个可行的选项。
主要代码:
(ns clj.core
(:require
[tupelo.core :as t]
))
(t/refer-tupelo)
(def myLis [ [3 3] [5 5] [5 5] ] )
(def som [4 4] )
(spyx (assoc myLis 1 som))
(spyx (assoc-in myLis [1] som))
(defn -main [& args]
(println "-main"))结果:
~/clj > lein run
(assoc myLis 1 som) => [[3 3] [4 4] [5 5]]
(assoc-in myLis [1] som) => [[3 3] [4 4] [5 5]]在project.clj中需要这样做才能使(spy ...)工作:
:dependencies [
[tupelo "0.9.9"]
...更新2016-11-2:
如果确实希望将所有内容都保存在列表中,可以使用replace-at 从图佩洛图书馆。它的工作方式如下:
(def myLis '( (3 3) (5 5) (5 5) ) )
(def vec-1 [4 4] )
(def list-1 '(4 4) )
(spyx (t/replace-at myLis 1 vec-1 ))
(spyx (t/replace-at myLis 1 list-1))
(spyx (apply list (t/replace-at myLis 1 list-1)))有结果
> lein run
(t/replace-at myLis 1 vec-1) => [(3 3) [4 4] (5 5)]
(t/replace-at myLis 1 list-1) => [(3 3) (4 4) (5 5)]
(apply list (t/replace-at myLis 1 list-1)) => ((3 3) (4 4) (5 5))前两个示例显示,新元素可以是任何东西,例如向量[4 4]或列表(4 4)。另外,请注意,replace-at总是返回一个向量结果。如果您希望最终结果也是一个列表,则需要使用(apply list <some-collection>)。
发布于 2016-11-03 07:30:39
使用列表我的解决方案:
(def newL '())
(def i 1)
(loop [k (- (count myLis) 1)]
(when (> k -1)
(cond
(= k i) (def newL (conj newL som))
:else (def newL (conj newL (nth myLis k)))
)
(recur (- k 1))
)
)https://stackoverflow.com/questions/40370240
复制相似问题