clojure中的函数查找

clojure中的函数查找,clojure,Clojure,帮助我,我需要编写查找函数,查找列表中的值,因为每个元素都是按顺序排列的键值。 比如说 ((key1 value1) (key2 value2) ....) 此功能需要重新设置 (look-up key list-of-lists) 并返回具有键的列表的值。 例如: (look-up b '(((a b) 1) (c 2) (b 3)))3 (look-up (a b) '(((a b) 1) (c 2) (b 3)))1 (look-up d '(((a b) 1) (c 2) (b 3)

帮助我,我需要编写查找函数,查找列表中的值,因为每个元素都是按顺序排列的键值。 比如说

((key1 value1) (key2 value2) ....)
此功能需要重新设置

(look-up key list-of-lists)
并返回具有键的列表的值。 例如:

(look-up b '(((a b) 1) (c 2) (b 3)))3
(look-up (a b) '(((a b) 1) (c 2) (b 3)))1
(look-up d '(((a b) 1) (c 2) (b 3)))nil
我有以下代码:

(defn look-up [key list-of-lists]
  (if (= key (first(first list-of-lists))) (second(first list-of-lists)))
  (:else (look-up (rest list-of-lists key))))

下面是一个简单的版本:

(defn lookup
  [k lol]
  (let [the-map (into {}
                  (for [lst lol]
                    {(first lst) (second lst) } ))
        result (get the-map k)]
    result ) )

(lookup (quote b)      (quote (((a b) 1) (c 2) (b 3)))) => 3
(lookup (quote [a b])  (quote (((a b) 1) (c 2) (b 3)))) => 1
(lookup (quote d)      (quote (((a b) 1) (c 2) (b 3)))) => nil
但是,如果您将所有带引号的列表(如“1 2 3”)替换为向量(如[1 2 3]),则不需要前导引号,并将所有带引号的符号(如“a”)替换为关键字(如:a也不需要引用符号),则代码将更简单

进行这些更改并添加单元测试如下所示:

(ns tst.demo.core
  (:use tupelo.core demo.core tupelo.test) )

(defn lookup
  [k lol]
  (get (into {} lol) k))

(dotest
  (is= 3    (lookup :b      [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= 1    (lookup [:a :b] [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= nil  (lookup :d      [[[:a :b] 1] [:c 2] [:b 3]])))
请注意,了解更多详情

更新:

您不能使用具有以下语法的常规函数:

(look-up b '(((a b) 1) (c 2) (b 3)))
因为b是一个符号,意味着是一个变量,而不是一段数据。您的选择:

按照我的建议,将符号b转换为关键字:b 始终引用“b”之类的符号,这很痛苦且容易出错 编写一个自动引用其所有参数的宏,并让该宏调用第一个版本的查找函数,这会带来很多小好处。
这就是我建议将第1项作为首选解决方案的方式。

以下是一个简单的版本:

(defn lookup
  [k lol]
  (let [the-map (into {}
                  (for [lst lol]
                    {(first lst) (second lst) } ))
        result (get the-map k)]
    result ) )

(lookup (quote b)      (quote (((a b) 1) (c 2) (b 3)))) => 3
(lookup (quote [a b])  (quote (((a b) 1) (c 2) (b 3)))) => 1
(lookup (quote d)      (quote (((a b) 1) (c 2) (b 3)))) => nil
但是,如果您将所有带引号的列表(如“1 2 3”)替换为向量(如[1 2 3]),则不需要前导引号,并将所有带引号的符号(如“a”)替换为关键字(如:a也不需要引用符号),则代码将更简单

进行这些更改并添加单元测试如下所示:

(ns tst.demo.core
  (:use tupelo.core demo.core tupelo.test) )

(defn lookup
  [k lol]
  (get (into {} lol) k))

(dotest
  (is= 3    (lookup :b      [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= 1    (lookup [:a :b] [[[:a :b] 1] [:c 2] [:b 3]]))
  (is= nil  (lookup :d      [[[:a :b] 1] [:c 2] [:b 3]])))
请注意,了解更多详情

更新:

您不能使用具有以下语法的常规函数:

(look-up b '(((a b) 1) (c 2) (b 3)))
因为b是一个符号,意味着是一个变量,而不是一段数据。您的选择:

按照我的建议,将符号b转换为关键字:b 始终引用“b”之类的符号,这很痛苦且容易出错 编写一个自动引用其所有参数的宏,并让该宏调用第一个版本的查找函数,这会带来很多小好处。
这就是我建议将项目1作为首选解决方案的方式。

您的代码几乎是正确的。我解决的两件事是:

if的语法包含3个参数:一个测试和测试的每个布尔结果的两个值。在使用cond时,通常不需要:else来突出显示默认分支

继续查看列表其余部分的递归调用的参数顺序错误

修正后的函数如下所示:

(defn look-up [key list-of-lists]                                                                                                                                                    
  (if (= key (first (first list-of-lists)))                                                                                                                                          
    (second (first list-of-lists))                                                                                                                                                   
    (look-up key (rest list-of-lists))))                                                                                                                                             

;; (look-up 'b '(((a b) 1) (c 2) (b 3))) ;; => returns 3                                                                                                                             
注:

您可以使用其他函数(如ffirst)简化此代码,请参阅 您仍然需要改进它以涵盖以下情况:1。-和2。-查找不存在的密钥。如果调用查找“x”ab1c2b3,会发生什么?
你的代码几乎是正确的。我解决的两件事是:

if的语法包含3个参数:一个测试和测试的每个布尔结果的两个值。在使用cond时,通常不需要:else来突出显示默认分支

继续查看列表其余部分的递归调用的参数顺序错误

修正后的函数如下所示:

(defn look-up [key list-of-lists]                                                                                                                                                    
  (if (= key (first (first list-of-lists)))                                                                                                                                          
    (second (first list-of-lists))                                                                                                                                                   
    (look-up key (rest list-of-lists))))                                                                                                                                             

;; (look-up 'b '(((a b) 1) (c 2) (b 3))) ;; => returns 3                                                                                                                             
注:

您可以使用其他函数(如ffirst)简化此代码,请参阅 您仍然需要改进它以涵盖以下情况:1。-和2。-查找不存在的密钥。如果调用查找“x”ab1c2b3,会发生什么?
只是一点点模式匹配

(require '[meander.match.alpha :as pm])
(letfn [(lookup [KEY LIST]
            (pm/find LIST
                     (_ ... (~KEY ?v) . _ ...) ?v))]
    (let [LIST '(((a b) 1) (c 2) (b 3))]
        [(lookup 'b LIST)
         (lookup '(a b) LIST)
         (lookup 'd LIST)]))
=> [3 1 nil]

对于这样一个简单的案例来说,这是一个过火的举动,但这里为一些更高级的用例提供了线索。

只是一点模式匹配

(require '[meander.match.alpha :as pm])
(letfn [(lookup [KEY LIST]
            (pm/find LIST
                     (_ ... (~KEY ?v) . _ ...) ?v))]
    (let [LIST '(((a b) 1) (c 2) (b 3))]
        [(lookup 'b LIST)
         (lookup '(a b) LIST)
         (lookup 'd LIST)]))
=> [3 1 nil]
(defn lookup [x xs]
  (first (for [[k v] xs :when (= k x)]
           v)))

对于这样一个简单的案例来说,这是一个过火的举动,但这里提供了一些更高级用例的线索。

如果您想在列表中找到符合某些条件的第一项,请检查该项的第一个元素,然后对该项执行一些操作,以获取其第二个元素

(defn lookup [x xs]
  (first (for [[k v] xs :when (= k x)]
           v)))
建议使用一些或筛选器来搜索序列

一些 defn查找 [x列] 一些fn[[k v]] 当=x k v 上校 滤器 defn查找 [x列] ->>上校 过滤器fn[[k v]] 当=x k v 第一 列表理解 这也是一个不错的选择。看

通用解决方案,如果你想变得疯狂 您可以使用上述任何一种方法来执行此操作

defn查找 [pred f col] 一些fn[x] 当pred x f x 上校 defn查找 [pred f col] 第一个用于[x列:当pred x时] f x ;; 用法:查找comp'{b}第一秒数据
您希望在列表中找到符合某些条件的第一项检查该项的第一个元素,然后对该项执行某些操作以获取其第二个元素

建议使用一些或筛选器来搜索序列

一些 defn查找 [x列] 一些fn[[k v]] 当=x k v 上校 滤器 defn查找 [x列] ->>上校 过滤器fn[[k v]] 当=x k v 第一 列表理解 这也是一个不错的选择。看

泛型s 如果你想发疯,那就解决吧 您可以使用上述任何一种方法来执行此操作

defn查找 [pred f col] 一些fn[x] 当pred x f x 上校 defn查找 [pred f col] 第一个用于[x列:当pred x时] f x ;; 用法:查找comp'{b}第一秒数据
对于本例,查找“x”ab1c2b3结果需要为零,但我不知道如何做到这一点。解决这两个问题的最简单更改是检查列表中是否还有元素。如果没有,它从一开始就是空的,或者你已经检查过了。在这种情况下,类似于用检查列表是否不为空来包装if:defn look-up[key list of list]if not empty?列表列表if=key…对于本例,查找“x”ab1c2b3结果需要为零,但我不知道如何做到这一点。解决这两个问题的最简单更改是检查列表上是否还有任何元素。如果没有,它从一开始就是空的,或者你已经检查过了。在这种情况下,类似于用检查列表是否不为空来包装if:defn look-up[key list of list]if not empty?列表列表if=key…建议用向量替换映射信息[lst lol]{first lst second lst}。一个单一的地图条目在这里可以作为一个地图条目,这肯定是一个意外,它不是一个地图条目。Into可以将一系列映射合并为{}[{:A1,:B2}{:C3,:D4}]=>{:A1,:B2,:C3,:D4}。事实上,Clojure将2向量作为人造地图条目进行的特殊处理是令人费解的。不同意。文档说into to coll from coll返回一个由to coll组成的新coll,其中from coll的所有项都连接在一起。核心实现是错误的。如果Clojure是静态类型的,那么错误是显而易见的。不幸的是,docstring可能会给人错误的印象。源代码的操作行是reduce conj to from.Yes。问题在于conj:conj{1 2}{3 4,5 6}产生的{1 2,3 4,5 6}是错误的。签名应该是coll[X]X->coll[X]。同样,静态类型将暴露不一致性。我想知道核心规范有什么要说的。建议你用向量替换映射infor[lstlol]{first-lst-second-lst}。一个单一的地图条目在这里可以作为一个地图条目,这肯定是一个意外,它不是一个地图条目。Into可以将一系列映射合并为{}[{:A1,:B2}{:C3,:D4}]=>{:A1,:B2,:C3,:D4}。事实上,Clojure将2向量作为人造地图条目进行的特殊处理是令人费解的。不同意。文档说into to coll from coll返回一个由to coll组成的新coll,其中from coll的所有项都连接在一起。核心实现是错误的。如果Clojure是静态类型的,那么错误是显而易见的。不幸的是,docstring可能会给人错误的印象。源代码的操作行是reduce conj to from.Yes。问题在于conj:conj{1 2}{3 4,5 6}产生的{1 2,3 4,5 6}是错误的。签名应该是coll[X]X->coll[X]。同样,静态类型将暴露不一致性。我想知道核心规范有什么要说的。