【问题标题】:How to convert a lazy sequence to a map?如何将惰性序列转换为地图?
【发布时间】:2018-04-06 13:05:32
【问题描述】:

我有一个惰性序列,当发送到 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",这将是我的问题的重复,如果不是问题和答案看起来都复杂得多,以至于我不知道如何将该解决方案转化为我自己的场景

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

  • X:如何在控制台上以表格的形式漂亮地打印一对字符串对的惰性序列?
  • Y:如何将惰性序列转换为映射(例如,键是索引)?

【问题讨论】:

  • (apply hash-map (flatten data)) => {purple cat, yellow bird, green mouse, red dog}
  • 但是如果最里面的列表有超过 2 个项目,这仍然有效吗? (我可能需要在我的问题中澄清可能发生的问题 - 我的数据来自具有 当前 2 列的 CSV,稍后会更多。)
  • 第一个显然是错误的。以下适用于任意数量的值,按整数索引它们(print-table (map #(zipmap (range) %) (apply concat data)))

标签: clojure


【解决方案1】:

如何在控制台上以表格形式漂亮地打印一对字符串对的惰性序列?

假设您想要一个包含颜色/动物的两列表,那么您的“行”似乎成对分组的事实很奇怪,因此我们可以使用 mapcat identity 然后 zipmap 删除额外的分组所需的地图关键字:

(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 |

这个问题并不清楚,但似乎你想支持任意数量的“列”,这有点排除了它们的固定名称。在这种情况下,您可以执行以下操作:

(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))}

【讨论】:

  • 我现在意识到我的问题不清楚(因为我自己显然不清楚我想要什么),但这回答了我问 AFAICT 的问题,无论如何最后一点帮助我理解事情足以进行。感谢您的宝贵时间!
【解决方案2】:

与您的问题相关的一点是您如何打印数据。 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 来区分符号和字符串。请注意,如果您使用pprint,则prn 输出格式(带有双引号)会自动发生:

(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"]]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2011-11-22
    • 2012-06-16
    相关资源
    最近更新 更多