如何将懒惰序列转换为地图?

时间:2018-04-06 13:05:32

标签: clojure

我有一个懒惰的序列,当发送到println时,显示如下:

(((red dog) (purple cat)) ((green mouse) (yellow bird)))

请注意,这是读取csv并修剪所有“单元格”值的结果,因此(a)在我想要打印它时它很懒,而且(b)将来最里面的列表可能更多超过2个字符串,因为添加了更多列。

我正试图让clojure.pprint/print-table在两列表中打印出来。我很难过,因为print-table似乎想要一个map数据。

这是一个复制品:

;; Mock the lazy data retrieved from a csv file
(defn get-lazy-data []
  (lazy-seq '('('("red" "dog") '("purple" "cat")) '('("green" "mouse") '("yellow" "bird")))))

(defn -main []
  (let [data       (get-lazy-data)]
      (println "Starting...")
      (println data)
      (println "Continuing...")
      (print-table data)
      (println "Finished!")))

这会出错:

  

线程“main”中的异常java.lang.ClassCastException:clojure.lang.Symbol无法强制转换为java.util.Map $ Entry

我尝试过各种选择:

  • (print-table (apply hash-map data))提供相同的例外
  • (print-table (zipmap data))告诉我为键提供另一个参数,但我想要一个不依赖于预先指定列数的解决方案
  • 理解和改编the answer to "Clojure printing lazy sequence",这将是我的问题的重复,并不是问题和答案都变得如此复杂,以至于我不知道如何将该解决方案转换为我自己的方案< / LI>

基本上我知道我有an XY-problem但现在我想要回答这两个问题:

  • X:我如何在控制台上打印一对字符串对的懒惰序列?
  • Y:如何将延迟序列转换为地图(例如,键是索引)?

2 个答案:

答案 0 :(得分:3)

  

如何在控制台上打印一对字符串对的懒惰序列?

你的&#34;行&#34;似乎是成对分组是假的,假设你想要一个双列的颜色/动物表,所以我们可以删除额外的分组mapcat identity然后zipmap那些具有所需地图关键字的对:< / p>

(def my-list
  '(((red dog) (purple cat)) ((green mouse) (yellow bird))))
(def de-tupled (mapcat identity my-list))
(map #(zipmap [:color :animal] %) de-tupled)
=> ({:color red, :animal dog} {:color purple, :animal cat} {:color green, :animal mouse} {:color yellow, :animal bird})

(clojure.pprint/print-table *1)
| :color | :animal |
|--------+---------|
|    red |     dog |
| purple |     cat |
|  green |   mouse |
| yellow |    bird |

问题不明确,但似乎你想支持任意数量的&#34;列&#34;哪一种排除了他们的固定名称。在这种情况下,你可以这样做:

(def my-list ;; added third mood "column"
  '(((red dog happy) (purple cat sad)) ((green mouse happy) (yellow bird sad))))
(def de-tupled (apply concat my-list))
(clojure.pprint/print-table (map #(zipmap (range) %) de-tupled))
|      0 |     1 |     2 |
|--------+-------+-------|
|    red |   dog | happy |
| purple |   cat |   sad |
|  green | mouse | happy |
| yellow |  bird |   sad |
  

如何将延迟序列转换为地图(例如,键是索引)?

(def my-list
  '(((red dog) (purple cat)) ((green mouse) (yellow bird))))
(zipmap (range) my-list)
=> {0 ((red dog) (purple cat)), 1 ((green mouse) (yellow bird))}

答案 1 :(得分:0)

与您的问题相关的一点是如何打印数据。 Clojure有两种打印方式:

(dotest
  (println ["hello" "there" "everybody"])      ; #1
  (prn     ["hello" "there" "everybody"]))     ; #2

#1  => [hello there everybody]
#2  => ["hello" "there" "everybody"]

对于字符串,#2中引号的存在对理解正在发生的事情有很大的不同。 prn函数生成机器可读的输出(就像您在源代码中键入的内容一样)。如果您的数据中包含字符串,那么您确实需要这样做。

查看与符号的区别:

  (println ['hello 'there 'everybody])
  (prn     ['hello 'there 'everybody])

  ; doesn't matter if you quote the whole form or individual symbols    
  (println '[hello there everybody])
  (prn     '[hello there everybody])

所有结果都是一样的:

[hello there everybody]
[hello there everybody]
[hello there everybody]
[hello there everybody]

重点是,在打印结果时,需要prn来区分符号和字符串。请注意,如果您使用prnpprint输出格式(带双引号)会自动发生:

(def data
  [["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]
   ["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]
   ["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]])

(clojure.pprint/pprint data) =>
  [["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]
   ["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]
   ["here" "we" "have" "a" "lot" "of" "strings" "in" "vectors"]]