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]。同样,静态类型将暴露不一致性。我想知道核心规范有什么要说的。