Clojure学习2-----常用函数

常用函数
1 conj(连词)

往瞬态集合中添加X

(conj [1 3 4]5)
=>[1 3 4 5]
2 recur复发

尾递归的时候的时候用着,recur会将一个尾递归转换为一个不需要消耗栈的循环.
recur调用循环使用新值,loop是recur的递归点

3 first和rest

first(返回第一项)和 rest(返回集合中第一项之后的其余项)

4 reduce-kv

结构:(reduce-kv f init coll)=>(reduce-kv 函数 初始值 操作序列)

  • 函数接受的参数可以是向量或者多个列表,但是他们的fn的值不一样

reduce-kv 和assoc 组合使用
例1.把矢量中的中每一个清单中的每一项数据都进行 +1

;;定义需要操作的数据
(def vector-of-maps [{:a 1 :b 2} {:a 3 :b 4}])
;;定义一个函数,进行数据+1操作
(defn update-map [m f]
  (println "===="m "*******" f)  
  (reduce-kv (fn [m k v]      ;; k表示key,v表示value   
               (println "===="m "*******" k "&&&&&&" v)
               (assoc m k (f v))) {} m))
;;调用函数
(map #(update-map % inc) vector-of-maps)

打印函数数据的解析过程:

(map #(update-map % inc) vector-of-maps)
==== {:a 1, :b 2} ******* #object[clojure.core$inc 0x60a91f0 clojure.core$inc@60a91f0]
==== {} ******* :a &&&&&& 1
==== {:a 2} ******* :b &&&&&& 2
==== {:a 3, :b 4} ******* #object[clojure.core$inc 0x60a91f0 clojure.core$inc@60a91f0]
==== {} ******* :a &&&&&& 3
==== {:a 4} ******* :b &&&&&& 4
=> ({:a 2, :b 3} {:a 4, :b 5})

例2:两个清单A,B,若B清单和A清单有相同的key,则把A清单中key对应的值换成B中的,若key不同,则把k-v放入到A清单中,组装成新的清单

(reduct-kv fn  m e)  =>m是初始值,e是操作序列
(defn update-map-entries[m e]
  (println "======="m "&&&&&&" e)
  (reduce-kv (fn [r k v ]  ;;r对应的是第一个{}, k和v是从第二个{}中找
  						 (println "######"r "&&&&&&" k "====="v) 
  						 (assoc  r k v))  m e)) 

函数数据解析:

(update-map-entries {:a 1 :b 2 :c 3} {:a 5 :b 9})
======= {:a 1, :b 2, :c 3} &&&&&& {:a 5, :b 9}
###### {:a 1, :b 2, :c 3} &&&&&& :a ===== 5
###### {:a 5, :b 2, :c 3} &&&&&& :b ===== 9
=> {:a 5, :b 9, :c 3}

(update-map-entries {:a 1 :b 2 :c 3} {:a 5 :b 9 :d 8})
=> {:a 5, :b 9, :c 3, :d 8}
5 mapv

结构:(mapv f coll)(mapv f c1 c2)(mapv f c1 c2 c3)(mapv f c1 c2 c3 & colls)
mapv 把

6 merge 合并

返回一个映射,其中包含其他映射到的映射
首先。如果一个键出现在多个映射中,则映射来自
后者(从左到右)将是结果中的映射。

;;   :b键重复多次,最后的结果是从左向右的后者 
(merge { :a 1 :b 2 :c 3 } { :b 9 :d 4 } );; => {:d 4,:a 1,:b 9,:c 3}          
7 even? (是否为偶数) odd? (是否为基数)
(even? 2) ===>true
(odd? 3)>true
8 range (范围)
(range 5) ===>(1 2 3 4)
(range 8)===>(1 2 3 4 5 6 7)
9 select-keys

结构:(select-keys map keyseq)
例子:选出map中 :a :c 键所对应的key value值

user=> (select-keys {:a 1 :b 2 :c 3} [:a :c])
{:c 3, :a 1}
10 group-by (分组)

结构:(group-by f coll) 按某个键进行分组,把某个键的值提出来
例子:

(group-by :user-id [{:user-id 1 :uri "/"} 
                    {:user-id 2 :uri "/foo"} 
                    {:user-id 1 :uri "/account"}])
;; 按:user-id进行分组,把:user-id的值提出来
;;=> {1 [{:user-id 1, :uri "/"} 
;;       {:user-id 1, :uri "/account"}],
;;    2 [{:user-id 2, :uri "/foo"}]}

注: 单纯的用group by进行分组,只是把key对应的value提出来,有时候满足不了我们的需求,我们需要把 整个key-value 提出来,这个时候还需要一个函数,组合使用才能完成。一般用group by 和select-keys 进行分组过滤
定义函数:

(defn grouped-by-keys
  ([data group-keys]
   (->> data
        (group-by (fn [m] (select-keys m group-keys))))))
;;开始调用函数
(grouped-by-keys entries1 [:val])
;;结果
=>
{{:val "hello"} [{:month 1, :val "hello", :s1 true, :s2 false}
                 {:month 9, :val "hello", :s1 true, :s2 false}
                 {:month 10, :val "hello", :s1 true, :s2 false}],
 {:val "nam"} [{:month 2, :val "nam", :s1 false, :s2 true}
               {:month 7, :val "nam", :s1 false, :s2 true}
               {:month 8, :val "nam", :s1 true, :s2 false}],
 {:val "cx"} [{:month 3, :val "cx", :s1 true, :s2 false}
              {:month 4, :val "cx", :s1 true, :s2 false}
              {:month 5, :val "cx", :s1 false, :s2 true}
              {:month 6, :val "cx", :s1 false, :s2 true}],
 {:val "font"} [{:month 11, :val "font", :s1 false, :s2 true} {:month 12, :val "font", :s1 false, :s2 true}]}

观察结果,感觉这样的结果看起来很别扭,希望把分组后的孩子们中的:val 都去掉,并且把孩子们放入到list,这样让人看起来比较直观易懂,把之前的函数改一改:

;;定义函数
(defn grouped-by-keys
  ([data group-keys]
   (->> data
        (group-by (fn [m] (select-keys m group-keys)))
+        (reduce-kv (fn [m k v]
+                    (assoc m k {:list
+                                 (mapv
+                                   (fn [e]
+                                    (apply dissoc e group-keys))
+                                  v)}))
+                   {}))))

调用函数,结果发生变化

;;结果
=>
{{:val "hello"} {:list [{:month 1, :s1 true, :s2 false}
                        {:month 9, :s1 true, :s2 false}
                        {:month 10, :s1 true, :s2 false}]},
 {:val "nam"} {:list [{:month 2, :s1 false, :s2 true} {:month 7, :s1 false, :s2 true} {:month 8, :s1 true, :s2 false}]},
 {:val "cx"} {:list [{:month 3, :s1 true, :s2 false}
                     {:month 4, :s1 true, :s2 false}
                     {:month 5, :s1 false, :s2 true}
                     {:month 6, :s1 false, :s2 true}]},
 {:val "font"} {:list [{:month 11, :s1 false, :s2 true} {:month 12, :s1 false, :s2 true}]}}

通过一次润色之后,这个结果看起来很简单、易懂、直观,但是认证看,发现内容的最外层是用一个{}括起来的,现在希望换成用一个[括起来],增加一行代码:

;;定义函数
(defn grouped-by-keys
  ([data group-keys]
   (->> data
        (group-by (fn [m] (select-keys m group-keys)))
        (reduce-kv (fn [m k v]
                     (assoc m k {:list
                                 (mapv
                                    (fn [e]
                                     (apply dissoc e group-keys))
                                    v)}))
                   {})
+        (mapv (fn [e] (apply merge e))))))

结果:

;;调用函数
(grouped-by-keys entries1 [:val])
;;结果
=>
[{:val "hello",
  :list [{:month 1, :s1 true, :s2 false} {:month 9, :s1 true, :s2 false} {:month 10, :s1 true, :s2 false}]}
 {:val "nam", :list [{:month 2, :s1 false, :s2 true} {:month 7, :s1 false, :s2 true} {:month 8, :s1 true, :s2 false}]}
 {:val "cx",
  :list [{:month 3, :s1 true, :s2 false}
         {:month 4, :s1 true, :s2 false}
         {:month 5, :s1 false, :s2 true}
         {:month 6, :s1 false, :s2 true}]}
 {:val "font", :list [{:month 11, :s1 false, :s2 true} {:month 12, :s1 false, :s2 true}]}]

现在结果看起来就很舒服了。

11 匿名函数

我们可以通过fn来声明一个匿名函数

user=> ((fn [name] (str "hello " name)) "world")
"hello world"

我们也可以通过def来给一个匿名函数设置名称:

user=> (def a (fn [name] (str "hello " name)))
#'user/a
user=> (a "world")
"hello world"

我们使用 % 来表明匿名函数的参数,如果有多个参数,则使用 %1 , %2 来获 取,使用 %& 来获取可变参数。

user=> (#(str "hello " %) "world")
"hello world"
user=> (#(str "hello " %1 " " %2) "world" "a ha")
"hello world a ha"
user=> (#(str "hello " %1 " " (clojure.string/join " " %&)) "world" "ha" "ha")
"hello world ha ha"
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值