【问题标题】:Removing the nth element of a vector in clojure在clojure中删除向量的第n个元素
【发布时间】:2016-01-26 02:26:49
【问题描述】:

我正在尝试在 clojure 中解决一个非常基本的问题,但在理解向量/列表的工作原理时遇到了一些麻烦。

首先,当我定义一个以向量作为参数的函数的参数时,你如何将其表示为参数。

你能不能把它作为一个变量说

(defn example [avector] (This is where the function goes) )

或者您是否必须事先列出向量或列表的每个元素?

(defn example [vectorpart1 vectorpart2 vectorpart3 vectorpart4 ] (This is where the function goes) )

另外,就向量和列表而言,有没有人知道可以计算向量长度或获取第一个/最后一个/或第 n 个元素的命令?

【问题讨论】:

标签: clojure


【解决方案1】:

要从向量v 中删除索引n 处的元素:

(defn remove-indexed [v n]
  (into (subvec v 0 n) (subvec v (inc n))))

例如,

(remove-indexed (vec (range 10)) 5)
;[0 1 2 3 4 6 7 8 9]

很多事情都可能出错:

  1. v 可能不是向量。
  2. n 可能不是整数。
  3. n 可能超出v 的范围(我们需要(contains? v n)

Clojure 在运行时检测所有这些错误。静态类型语言会在编译时检测到 1 和 2 而不是 3。

【讨论】:

    【解决方案2】:

    您的第一个示例定义了一个接受单个参数的函数,无论类型如何。如果您传递一个向量,那么该参数将被设置为一个向量。

    (example [1 2 3 4]) ;; (= avector [1 2 3 4])
    

    您的第二个示例定义了一个带有四个参数的函数。您需要传递四个单独的值才能使对该函数的调用有效。

    (example [1] [2] [3] [4])
    ;; (= vectorpart1 [1])
    ;; (= vectorpart2 [2])
    ;; (= vectorpart3 [3])
    ;; (= vectorpart4 [4])
    

    听起来您可能正在考虑解构语法,它允许您直接从参数向量中解构值。

    (defn example [[a b c d]]
      ())
    

    参数定义中的文字向量语法描述了第一个参数中的项目与函数范围内可用的符号之间的映射。

    (example [1 2 3 4])
    ;; (= a 1)
    ;; (= b 2)
    ;; (= c 3)
    ;; (= d 4)
    

    同样位于这个空间中的另一个函数是apply。 Apply 接受参数列表或向量,并就地调用函数。

    (defn example [a b c]
      (assert (= a 1))
      (assert (= b 2))
      (assert (= c 3)))
    

    如果我们用一个向量调用这个函数,你会得到一个 arity 异常。

    (example [1 2 3])
    ;; ArityException Wrong number of args (1) passed ...
    

    相反,我们可以使用apply 将向量作为参数传递。

    (apply example [1 2 3])
    ;; no errors!
    

    您可以在 Clojure 文档中找到使用向量所需的所有方法。

    如果你想删除一个特定的元素,只需将它之前的元素和它之后的元素,然后将它们连接在一起。

    (def v [1 2 3])
    (concat (subvec v 0 1) (subvec v 2))
    

    【讨论】:

      【解决方案3】:

      简短的回答是您的第一个示例是正确的。您不需要命名向量的每一部分,因为您通常会使用不确定长度的向量。如果您想对需要分配其部分的向量执行某些操作,可以通过destructuring 执行此操作。

      稍长一点的答案是发送到任何 clojure defn 的参数列表已经是一个向量。请注意,参数列表使用[] 包装其参数列表。这是因为在 Clojure 中代码和数据是一回事。来自this article...

      Lisps 是同音字,这意味着用该语言编写的代码被编码为该语言有工具可以操作的数据结构。

      这可能超出您的预期,但它是一个重要的相关概念。

      这里有一个简单的例子来帮助你...将一个向量(在这种情况下是字符串)传递给一个函数,它会返回这个向量。但是,如果您 map 覆盖它,它会将向量的内容连续传递给函数。

      user=> (def params ["bar" "baz"])
      #'user/params
      user=> (defn foo [params] (println params))
      #'user/foo
      user=> (foo params)
      [bar baz]
      nil
      user=> (map foo params)
      bar
      baz
      (nil nil)
      

      此外,请查看 Clojure cheatsheet 以了解更多关于您可以使用向量(以及 Clojure 中的所有其他内容)所做的事情。

      【讨论】:

      • 那么问题是我试图删除向量的第二个元素。因此,假设该函数接受一个包含 [0,1,2,3] 的向量。然后我需要它返回相同的向量,但删除了元素,所以我会得到 [0,1,3]
      • 那个问题已经有了答案:stackoverflow.com/questions/1394991/…
      • 1.请记住,它是零索引的。 2.你可能想要这个答案:stackoverflow.com/a/18319708/3662110
      • 好的,我让它工作了。我唯一需要做的就是弄清楚如何迭代一个向量例如,如果我有一个 (1 2 3 4) 的向量并且我想将每个元素相加。我必须弄清楚如何删除 1,然后是 2,然后是 3,然后是 4。当我不知道向量有多大以及如何删除时,我还需要弄清楚如何删除向量的最后一个元素根据它有多少元素,计算出一个向量有多大。
      • 这超出了您最初问题的范围。评论不是寻求更多帮助的地方。如果您有更多问题,您应该创建新问题。总的来说,听起来你需要花一些时间在 REPL 中自己解决这些问题。我建议您接受@DanPrince 的回答,因为它周到而透彻。
      猜你喜欢
      • 2012-03-06
      • 2012-09-19
      • 1970-01-01
      • 1970-01-01
      • 2019-11-21
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      • 2018-07-14
      相关资源
      最近更新 更多