Dictionary Clojure中的映射
如何让这段代码正常工作?它应该输出四个索引号,后跟从地图中随机选择的名称Dictionary Clojure中的映射,dictionary,clojure,Dictionary,Clojure,如何让这段代码正常工作?它应该输出四个索引号,后跟从地图中随机选择的名称 (def persons {0 "name1" 1 "name2" 2 "name3"}) (map #(println (str %1 ": " %2)) (iterate inc 0) (persons (rand-int 3))) 请不要建议其他方法,但请更正我的代码,如果你知道应该如何更正它。 它应该输出如下内容: 0:name2,1:name3,2:name1代码中的问题(persons(rand int 3)
(def persons {0 "name1" 1 "name2" 2 "name3"})
(map #(println (str %1 ": " %2)) (iterate inc 0) (persons (rand-int 3)))
请不要建议其他方法,但请更正我的代码,如果你知道应该如何更正它。
它应该输出如下内容:
0:name2,1:name3,2:name1代码中的问题
(persons(rand int 3))
从map中生成一个随机值,如“name3”,map将其视为一个字符序列(\n\a\m\e\3)
只需将其包装以调用几次:
(重复4#(个人(兰德国际3))
正确且更干净的方法:
(dotimes [i 4]
(println (str i ":" (rand-nth (vals persons)))))
- 如果需要副作用(打印),请使用
而不是dotimes
map
- 使用
而不是(rand nth(vals persons))
,如果地图增长并成为100个元素,则(persons(rand int 3))
仍会按预期运行,而rand nth
则基于地图大小rand int
- 如果您想遍历一系列内容并执行一些包含副作用的操作(如打印),则应使用
而不是mapdoseq
- 如果你在处理一个映射,那么你给
或map
的函数应该有一个参数,一个MapEntry——有点像一个包含键和值的两项列表。您可以使用解构来获取键和值doseq
您可以这样做:
- 这里有几点需要注意:
(def persons {0 "name1" 1 "name2" 2 "name3"})
(doseq [[i name] persons]
(println (str i ": " name)))
这并没有抓住你试图做的事情的随机性,但为此,我遵从@mishadoff的回答。我强烈建议“保持简单”,如下所示:
(def persons {0 "name1" 1 "name2" 2 "name3"})
(let [names (vals persons)
names-shuf (shuffle names)
idx (range (count names)) ]
(doseq [ii idx]
(println (str ii ": " (nth names-shuf ii)))))
产生:
~/clj > lein run
0: name2
1: name1
2: name3
或类似(每次都不同)。请注意,我们在这里使用shuffle,以确保映射中每个名称都有一个结果
map
接受一个函数和一个或多个集合。您为它提供了两个集合:一个惰性序列((iterate inc 0)
)和一个字符串((persons(rand int 3))
)。因此,您不是按随机顺序打印名称,而是按随机选择的字符串的顺序打印字符
我想你应该给它一组随机的名字。比如说,你想要的是:
(def persons {0 "name1" 1 "name2" 2 "name3"})
(def randomnames
(letfn [(makenames []
(lazy-seq (cons (persons (rand-int 3))
(makenames))))]
(makenames)))
(map #(println (str %1 ": " %2)) (take 3 (iterate inc 0)) (take 3 randomnames))
上述解决方案打印带有替换的随机名称;不用替换的话做起来会更复杂,但你明白了。该缺陷是,当您确实需要一组随机人(比如向量)时,您使用随机人作为映射的第二个参数。这是唯一正确使用
doseq
的解决方案,并且还显示了一个随机打印带有替换的名称的解决方案。