如何让这段代码正常工作?它应输出四个索引号,然后从地图中随机选择名称。
(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
答案 0 :(得分:4)
代码(persons (rand-int 3))
中的问题会从地图中生成一个随机值,例如" name3"和地图将其视为一系列字符(\n \a \m \e \3)
只需将其包裹几次即可:
(repeatedly 4 #(persons (rand-int 3)))
正确且更清洁的方式:
(dotimes [i 4]
(println (str i ":" (rand-nth (vals persons)))))
dotimes
代替map
(rand-nth (vals persons))
代替(persons (rand-int 3))
,如果您的地图增长并变为100个元素,rand-nth
仍然表现得像预期,而rand-int
则基于地图尺寸答案 1 :(得分:3)
这里有几点需要注意:
如果要迭代一系列事物并执行一些包含副作用的操作(如打印),则应使用doseq
而不是map。
如果你正在处理地图,你给map
或doseq
的函数应该有一个参数,一个MapEntry - 有点像一个2项列表包含密钥和值。您可以使用解构来获取密钥和值。
你可以这样做:
(def persons {0 "name1" 1 "name2" 2 "name3"})
(doseq [[i name] persons]
(println (str i ": " name)))
这并没有捕捉到你想要做的事情的随机性方面,但为此我遵从@ mishadoff的回答。
答案 2 :(得分:3)
我强烈建议“保持简单”如下:
(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
来确保地图中每个名称的确切结果为1。
答案 3 :(得分:2)
目前您的代码存在一些问题。首先,map
使用带副作用的方法(如编写输出)不是一个好主意。映射是一种懒惰的操作,所以当你认为它必然会发生。相反,你应该构建一个你想要的字符串列表,然后打印出来。
其次,map
期望其参数(映射函数除外)是可迭代的数据集合。但(persons (rand-int 3))
会从persons
中选择一个项目。这仍然有效,因为persons
中的值是字符串,但它没有做你想要的。我会改变你的代码(试图让它接近你原来的代码):
(def persons {0 "name1" 1 "name2" 2 "name3"}) ; Same data as before
(def output ; Making strings, instead of trying to print them inside the map
(map #(str % ": " (persons (rand-int 3))) ; Select one name for each number
(range 3))) ; Only take 3 items, so we don't have an infinite list
(println output) ; Actually display the result
答案 4 :(得分:2)
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))
以上解决方案使用替换打印随机名称;没有替换它的做法会更复杂,但你明白了。这个缺陷是你使用一个随机的人作为map
的第二个参数,当你真的想要一个随机人的集合时,比如说一个向量,他们都乱了。