【问题标题】:Clojure - get data inside vector of vectorsClojure - 获取向量向量内的数据
【发布时间】:2015-10-16 16:42:23
【问题描述】:

我有一个包含一些字符串和整数的向量向量:

(def data [
["a" "title" "b" 1]
["c" "title" "d" 1]
["e" "title" "f" 2]
["g" "title" "h" 1]
])

我正在尝试遍历向量并返回(?)任何包含特定字符串的行,例如“一种”。我尝试实现这样的事情:

(defn get-row [data]
  (for [d [data]
        :when (= (get-in d[0]) "a")] d
  ))

我对 Clojure 很陌生,但我相信这是在说:对于“数据”中的每个元素(向量),如果该向量包含“a”,则返回它?

我知道 get-in 需要 2 个参数,这部分是我不确定该怎么做的地方。

我看过thisthis 之类的答案,但我不太了解它们是如何工作的。据我所知,他们正在将矢量转换为地图并对其进行操作?

【问题讨论】:

    标签: clojure lighttable


    【解决方案1】:
    (filter #(some #{"a"} %) data)
    

    看到集合#{"a"} 有点奇怪,但它可以作为some 的谓词函数。向集合中添加更多条目就像是它的逻辑 OR,即

    (filter #(some #{"a" "c"} %) data)
    => (["a" "title" "b" 1] ["c" "title" "d" 1])
    

    【讨论】:

    • 谢谢,这行得通,但我不确定如何?我认为您正在做的是针对仅包含“a”的集合过滤数据中的所有元素(%)是否正确?
    • {filter down data by { 是否有 some 元素被 {set "a" } 识别? } }
    • 在 Clojure 中,集合除了是一种数据结构外,也是一种函数。将函数 #{"a" "b"} 应用于一个值将返回该值,如果它是“a”或“b”,否则它将返回 nil。 some 依次对序列中的每个值应用一个函数,直到找到一个返回真值的函数。 filter 遍历序列中的每个元素,并且只保留那些为您提供的函数返回真实值的元素。我建议您在 REPL tryclj.com 中使用所有 3 个函数
    【解决方案2】:

    好的,你的代码有错误

    (defn get-row [data]
      (for [d [data]
            :when (= (get-in d[0]) "a")] d
      ))
    

    错误在这里: (for [d [data] ... 遍历所有不应将 data 括在括号中的元素,因为此语法用于创建向量。在这里,您试图遍历一个元素的向量。这就是 clojure 的样子:

        (for [d [[["a" "title" "b" 1]
                  ["c" "title" "d" 1]
                  ["e" "title" "f" 2]
                  ["g" "title" "h" 1]]] ...
    

    所以,正确的变体是:

    (defn get-row [data]
      (for [d data
            :when (= "a" (get-in d [0]))]
        d))
    

    那么,您可以为此使用 clojure' 解构:

    (defn get-row [data]
      (for [[f & _ :as d] data
            :when (= f "a")]
        d))
    

    但更clojuric的方式是使用高阶函数:

    (defn get-row [data]
      (filter #(= (first %) "a") data))
    

    这是关于您的代码的。但是其他人的答案中有正确的变体,因为在这里您只检查第一项。

    【讨论】:

    • 感谢您的解释,我知道我现在哪里出错了。
    【解决方案3】:
    (defn get-row [data]
      (for [d data ; <-- fix: [data] would result 
                   ; in one iteration with d bound to data
            :when (= (get-in d[0]) "a")]
        d))
    

    请注意,您的算法返回第一列为“a”的行。这可以e。 G。使用some 和集合作为谓词函数来扫描整行来解决。

    (defn get-row [data]
      (for [row data
            :when (some #{"a"} row)]
        row))
    

    【讨论】:

      【解决方案4】:

      甚至比当前选择的答案更好,这会起作用:

      (filter #(= "a" (% 0)) data)
      

      这样做的原因是因为对于最佳答案,您正在搜索查询的子向量的所有索引,而您可能只想查看每个子向量的第一个索引 (在这种情况下,在每个位置 0 中搜索“a”,如果为 true,则返回整个子向量)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 2010-11-05
        • 2012-10-08
        • 1970-01-01
        相关资源
        最近更新 更多