帮我,我需要编写查找函数,该函数在列表中查找值,因为每个元素都是按顺序排列的(键值)。 例如
((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))))
答案 0 :(得分:3)
(defn lookup [x xs]
(first (for [[k v] xs :when (= k x)]
v)))
答案 1 :(得分:2)
这是一个可以使用的简单版本:
(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]
这样的向量(那么就不需要前导引号),并替换所有引号,例如{ {1}}带有诸如'a
之类的关键字(也不需要引用符号。
进行这些更改并添加单元测试如下所示:
:a
P.S。请see Brave Clojure了解更多详情。
更新:
您不能使用具有以下语法的常规函数:
(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)作为首选解决方案的方式。
答案 2 :(得分:1)
您的代码几乎正确。我修复的两件事是:
“ if”的语法带有3个参数:一个测试和两个值(对于该测试的每个布尔结果)。不需要:else
(通常在使用cond
时用于突出显示默认分支。
继续查看其余列表列表的递归调用的参数顺序错误。
更正后的函数如下:
(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
简化此代码,请参见https://clojuredocs.org/clojure.core/ffirst (look-up 'x '(((a b) 1) (c 2) (b 3)))
会发生什么?答案 3 :(得分:1)
只需一点模式匹配...
(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]
对于这样一个简单的案例,这是一个过大的杀伤力,但是这里提供了一些更高级的使用案例的线索。
答案 4 :(得分:0)
您要在列表中找到符合某些条件的第一项(请检查该项的第一个元素),然后对该项做些事情(获取其第二个元素)。
Clojure cheatsheet建议使用some
或filter
搜索序列。
(defn lookup
[x col]
(some (fn [[k v]]
(when (= x k) v))
col))
(defn lookup
[x col]
(->> col
(filter (fn [[k v]]
(when (= x k) v)))
first))
也是一个不错的选择。参见amalloy's answer。
您可以使用上述任何一种方法来完成此操作。
(defn lookup
[pred f col]
(some (fn [x]
(when (pred x)
(f x)))
col))
(defn lookup
[pred f col]
(first (for [x col :when (pred x)]
(f x))))
;; usage: (lookup (comp '#{b} first) second data)