我有一个包含以下文字的文件:
1|apple|sweet
2|coffee|bitter
3|gitpush|relief
我想使用地图处理此输入。在Java或Python中,我会创建一个嵌套映射,如:
{1: {thing: apple, taste: sweet},
2: {thing: coffee, taste: bitter},
3: {thing: gitpush, taste: relief}}
甚至地图中的列表如:
{1: [apple, sweet],
2: [coffee, bitter],
3: [grape, sour]}
最终目标是使用第一列作为密钥有效地访问最后两列的数据。 我想在Clojure中做到这一点,我是新手。到目前为止,我已成功使用以下代码创建地图列表:
(def cust_map (map (fn [[id name taste]]
(hash-map :id (Integer/parseInt id)
:name name
:taste taste ))
(map #(str/split % #"\|") (line-seq (clojure.java.io/reader path)))))
我明白了,但这不是我想要的。
({1, apple, sweet},
{2, coffee, bitter},
{3, gitpush, relief})
如果您能告诉我如何在Clojure中执行最有效的嵌套地图和列表内容,那将是很好的。谢谢!
答案 0 :(得分:1)
使用hash-map
构建地图时,参数是替代键和值。例如:
(hash-map :a 0 :b 1)
=> {:b 1, :a 0}
根据我的理解,你想要一个唯一的键,整数,映射到复合对象,地图:
(hash-map 0 {:thing "apple" :taste "sweet"})
此外,您不想调用map
,这会导致一系列地图。您希望构建一个哈希映射。
尝试使用reduce
:
(reduce (fn [map [id name taste]]
(merge map
(hash-map (Integer/parseInt id)
{:name name :taste taste})))
{}
'(("1" "b" "c")
("2" "d" "e")))
---编辑
这是完整的测试程序:
(import '(java.io BufferedReader StringReader))
(def test-input (line-seq
(BufferedReader.
(StringReader.
"1|John Smith|123 Here Street|456-4567
2|Sue Jones|43 Rose Court Street|345-7867
3|Fan Yuhong|165 Happy Lane|345-4533"))))
(def a-map
(reduce
(fn [map [id name address phone]]
(merge map
(hash-map (Integer/parseInt id)
{:name name :address address :phone phone})))
{}
(map #(clojure.string/split % #"\|") test-input)))
a-map
=> {1 {:name "John Smith", :address "123 Here Street", :phone "456-4567"}, 2 {:name "Sue Jones", :address "43 Rose Court Street", :phone "345-7867"}, 3 {:name "Fan Yuhong", :address "165 Happy Lane", :phone "345-4533"}}
答案 1 :(得分:1)
我同意@coredump这不简洁,但代码的快速解决方案是使用列表(或任何其他集合)和嵌套映射:
(def cust_map (map (fn [[id name taste]]
(list (Integer/parseInt id)
(hash-map :name name
:taste taste)))
(map #(clojure.string/split % #"\|") (line-seq (clojure.java.io/reader path)))))
答案 2 :(得分:1)
这对我来说可能有些天真,因为我并不是Clojure所经历过的所有事情,但是每当我想从一个集合中制作地图时,我会立即想到zipmap
:< / p>
(require '[clojure.java.io :as io :refer [reader]])
(defn lines-from [fname]
(line-seq (io/reader fname)))
(defn nested-map [fname re keys]
"fname : full path and filename to the input file
re : regular expression used to split file lines into columns
keys : sequence of keys for the trailing columns in each line. The first column
of each line is assumed to be the line ID"
(let [lines (lines-from fname)
line-cols (map #(clojure.string/split % re) lines) ; (["1" "apple" "sweet"] ["2" "coffee" "bitter"] ["3" "gitpush" "relief"])
ids (map #(Integer/parseInt (first %)) line-cols) ; (1 2 3)
rest-cols (map rest line-cols) ; (("apple" "sweet") ("coffee" "bitter") ("gitpush" "relief"))
rest-maps (map #(zipmap keys %) rest-cols)] ; ({:thing "apple", :taste "sweet"} {:thing "coffee", :taste "bitter"} {:thing "gitpush", :taste "relief"})
(zipmap ids rest-maps)))
(nested-map "C:/Users/whatever/q50663848.txt" #"\|" [:thing :taste])
产生
{1 {:thing "apple", :taste "sweet"}, 2 {:thing "coffee", :taste "bitter"}, 3 {:thing "gitpush", :taste "relief"}}
我已将let
块中每个步骤的中间结果显示为评论,以便您了解正在进行的操作。我还在lines-from
投掷了line-seq
,这只是我BufferedReader.
周围的薄包裹,以免我不得不一直输入StringReader.
和for(int k=0; k<n; k++)
{
s=0
for(i=0; i<n; i++)
{
for (j=0; j<n; j *= 2)
{
s=s+i*j;
}
s=s+1
}
}
。 : - )