[英]Clojure function not returning a map
我是 Clojure 和函數式編程的新手。 我對 Clojure 中的數據結構(例如映射、列表和向量)有一個基本概念。
我正在嘗試編寫返回嵌套 map 的 function。 map 在 function 內正確顯示。 以下代碼來自read-customer-file
function
([input-list new-map place-holder]
(if (not-empty input-list)
(do
(def string-input (str (first input-list)))
(def cust-id (get (first input-list) 0))
(def cust-name (get (first input-list) 1))
(def cust-address (get (first input-list) 2))
(def cust-phone (get (first input-list) 3))
(def temp-map (conj new-map {(keyword cust-id) {:cust-name cust-name, :cust-address cust-address, :cust-phone cust-phone}}))
(read-customer-file (rest input-list) temp-map ())
)
(do
(map str new-map)
;(print (get-in new-map [:1 :cust-name]))
(print new-map)
)
)
)
這需要輸入向量列表,如下所示:
([3 Fan Yuhong 165 Happy Lane 345-4533] [2 Sue Jones 43 Rose Court Street 345-7867] [1 John Smith 123 Here Street 456-4567])
並返回一個嵌套映射,如下所示:
{:3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}, :2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}, :1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}}
這就是我想要實現的目標,並且在 function 中運行良好。 但是,如果我嘗試使用返回類型的值定義 function 之外的變量,我不會得到嵌套映射,而是字符串列表。 為此,我只刪除了(print new-map)
部分。
(do
(map str new-map)
)
並從 function 定義外部調用它,如下所示:
(def customer-info-list read-customer-file)
(println (customer-info-list))
我得到的結果與我的預期不同,無法執行get
和get-in
等地圖相關功能。
([:3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}] [:2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}] [:1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}])
我將非常感謝任何形式的幫助。 我知道我的代碼有點亂,我應該使用let
而不是def
作為變量名。 但我剛剛開始 Clojure 這是我的第一個程序。
更新
我解決了這個問題。 我所做的是將 map 更改為 function 內的排序映射。 因此,function 的最后一個返回值將是排序后的 map。
(do
(into (sorted-map) new-map)
)
但是,如果分配給變量,返回的值仍然是一個字符串。所以我再次將其轉換為排序映射。 然后它最終被轉換為嵌套地圖。
(def customer-info-list read-customer-file)
(def cust-map (into (sorted-map) (customer-info-list)))
(println cust-map)
(println (get-in cust-map [:1 :cust-name]))
(println (get cust-map :2))
上述三個打印語句中的 output 符合預期。
{:1 {:cust-name John Smith, :cust-address 123 Here Street, :cust-phone 456-4567}, :2 {:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}, :3 {:cust-name Fan Yuhong, :cust-address 165 Happy Lane, :cust-phone 345-4533}}
John Smith
{:cust-name Sue Jones, :cust-address 43 Rose Court Street, :cust-phone 345-7867}
您的代碼中有許多錯誤,與缺乏基本的 clojure 知識有關:
1) 不要在函數內部使用def/defn
,而是使用let
2) 添加到 map 通常使用assoc
完成
3) 從 function 中返回一些重要的值總是更好的,並在外部對其進行自省。
我會以更 clojure 的方式重寫你的 function :(我故意保留placeholder
參數,盡管它沒有在你的代碼中的任何地方使用,所以我無法推斷它的目的)
(defn read-customer-file [input-list new-map placeholder]
(if-let [[[id name address phone] & input-tail] (seq input-list)]
(read-customer-file input-tail
(assoc new-map (keyword id)
{:cust-name name
:cust-address address
:cust-phone phone})
())
new-map))
在回復中:
user> (read-customer-file [["a" "b" "c" "d"] ["e" "f" "g" "h"]] {} ())
;;=> {:a {:cust-name "b", :cust-address "c", :cust-phone "d"},
;; :e {:cust-name "f", :cust-address "g", :cust-phone "h"}}
但您真正需要的是一些高階數據處理 function ,例如map
:
(defn read-customer-file [input-list placeholder]
(into {}
(map (fn [[id name address phone]]
[(keyword id) {:cust-name name
:cust-phone phone
:cust-address address}])
input-list)))
user> (read-customer-file [["a" "b" "c" "d"] ["e" "f" "g" "h"]] {})
;;=> {:a {:cust-name "b", :cust-phone "d", :cust-address "c"},
;; :e {:cust-name "f", :cust-phone "h", :cust-address "g"}}
或reduce
:
(defn read-customer-file [input-list placeholder]
(reduce (fn [res [id name address phone]]
(assoc res (keyword id) {:cust-name name
:cust-phone phone
:cust-address address}))
{} input-list))
此外,將您的業務邏輯(在您的案例文件記錄到客戶轉換中)抽象為一些專門的 function 始終是一個好主意,以使處理 function 更通用:
(defn file-rec->customer [[id name address phone]]
[(keyword id) {:cust-name name
:cust-address address
:cust-phone phone}])
(defn read-data-file [record-processor input-list placeholder]
(into {} (map record-processor) input-list))
user> (read-data-file file-rec->customer [["a" "b" "c" "d"] ["e" "f" "g" "h"]] {})
;;=> {:a {:cust-name "b", :cust-address "c", :cust-phone "d"},
;; :e {:cust-name "f", :cust-address "g", :cust-phone "h"}}
我能夠通過在返回時將其轉換為排序地圖來解決問題。 此外,返回的值再次被轉換為一個排序映射,這可以解決問題。 請檢查更新部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.