代码之家  ›  专栏  ›  技术社区  ›  Jeroen

如何将惰性序列转换为映射?

  •  1
  • Jeroen  · 技术社区  · 8 年前

    我有一个懒散的序列,当发送到 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.符号不能转换为java。util。映射$条目

    我尝试了多种选择:

    • (print-table (apply hash-map data)) 给出相同的异常
    • (print-table (zipmap data)) 告诉我为键提供另一个参数,但我想要一个不依赖于预先指定列数的解决方案
    • 理解和适应 the answer to "Clojure printing lazy sequence" ,如果不是问题和答案看起来都非常复杂,我不知道如何将该解决方案转换为我自己的场景,那么这将是我的问题的重复

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

    • 十: 如何在控制台上漂亮地将成对字符串的惰性序列打印为一个表?
    • Y: 如何将惰性序列转换为映射(例如,键是索引)?
    2 回复  |  直到 8 年前
        1
  •  3
  •   Taylor Wood    8 年前

    如何在控制台上漂亮地将成对字符串的惰性序列打印为一个表?

    事实上,您的“行”似乎是成对分组的,这很奇怪,假设您想要一个颜色/动物的两列表,那么我们可以使用 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))}
    
        2
  •  0
  •   Alan Thompson    8 年前

    与您的问题相关的一点是如何打印数据。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公司 打印结果时区分符号和字符串。请注意 prn公司 如果使用 pprint :

    (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"]]
    
    推荐文章