Clojure 使用';对于';内部';让';返回哈希映射的列表

Clojure 使用';对于';内部';让';返回哈希映射的列表,clojure,Clojure,很抱歉标题不好,因为我不知道如何用10个词来描述。详情如下: 我希望以如下格式循环文件: a:1 b:2 我想循环每一行,收集所有的“k:v”到一个散列映射中 {a1,b2…} 我以“let”形式初始化一个散列映射,然后在let形式内用“for”循环所有行。 在每个循环步骤中,我使用“assoc”更新原始哈希映射 (让[myhash{}] (对于[第#{“A:1 B:2”“C:3 D:4”行) (对于[[k v](map#(clojure.string/split%1#“:”)对) 但最后我得到

很抱歉标题不好,因为我不知道如何用10个词来描述。详情如下:

我希望以如下格式循环文件:

a:1 b:2

我想循环每一行,收集所有的“k:v”到一个散列映射中

{a1,b2…}

我以“let”形式初始化一个散列映射,然后在let形式内用“for”循环所有行。 在每个循环步骤中,我使用“assoc”更新原始哈希映射

(让[myhash{}]

(对于[第#{“A:1 B:2”“C:3 D:4”行)

(对于[[k v](map#(clojure.string/split%1#“:”)对)

但最后我得到了一个懒散的散列映射,如下所示:

{{a1,b2…}{x98y99z100…}

我现在知道如何“合并”结果,但仍然不明白为什么“for”inside“let”返回 结果清单

我感到困惑的是:内部“for”中的“myhash”是否每次都是指以“let”形式声明的“myhash”?如果我真的想要一个类似输出的哈希映射列表,这是Clojure中惯用的方式吗?

Clojure“for”是一个,因此它创建了一个列表。它不是一个for循环。 此外,您似乎试图修改myhash,但Clojure的数据结构是不可变的。
我解决这个问题的方法是尝试创建一个pair-like([“a”1][“b”2]..)列表,并使用(进入{}pair-list of pair)

如果文件格式真的像您描述的那样简单,那么更简单的东西就足够了:

(apply hash-map (re-seq #"\w+" (slurp "your-file.txt")))
我认为,如果您使用:

slurp函数将整个文件读入一个字符串。
re-seq
函数将只返回文件中所有单词的序列(基本上与本例中的空格和冒号拆分相同)。现在您有了一个交替键值对序列,这正是
哈希映射
所期望的

我知道这并不能真正回答您的问题,但您确实询问了更多惯用的解决方案

我认为@dAni是对的,你对Clojure的一些基本概念(如不可变集合)感到困惑。我建议你通过一些练习来更加熟悉该语言。每次你解决一个问题时,你都可以将自己的解决方案与其他人的解决方案进行比较,并看到其他解决方案(可能更像idomatic)解决问题的方法


对不起,昨晚我在发布答案时没有仔细阅读你的代码。我刚刚意识到你实际上将值转换为浮点数。以下是一些选项

1)
partition
将输入序列划分为键/val对,这样您就可以
映射到键/val对上。既然您现在知道了如何划分一个对序列,您就可以使用
into
将它们全部添加到映射中

(->> "kvs.txt" slurp (re-seq #"\w") (partition 2)
     (map (fn [[k v]] [k (Float. v)])) (into {}))
2) 为映射声明一个值,并在结果中使用该值:

(defn map-values [m f]
  (into {} (for [[k v] m] [k (f v)])))

(->> "your-file.txt" slurp (re-seq #"\w+")
     (apply hash-map) (map-values #(Float. %)))
3) 如果您不介意使用符号键而不是字符串,那么可以安全地使用Clojure阅读器转换所有键和值

(->> "your-file.txt" slurp (re-seq #"\w+")
     (map read-string) (apply hash-map))
请注意,这是一种安全的使用,因为我们对
re-seq
的调用将过滤掉任何有害的输入。但是,这将为您提供long而不是float,因为像
1
这样的数字在Clojure中是长整数内部
中的
myhash
是否参考
中声明的
myhash
每次都让
形成吗

  • let
    myhash
    绑定到
    {}
    ,它永远不会反弹。
    myhash
    总是
    {}
  • assoc
    返回一个修改过的映射,但不改变
    myhash
因此,代码可以简化为

(for [line ["A:1 B:2" "C:3 D:4"]
      :let [pairs (clojure.string/split line #"\s")]]
  (for [[k v] (map #(clojure.string/split %1 #":") pairs)]
    (assoc {} k (Float. v))))
…产生相同的结果:

(({"A" 1.0} {"B" 2.0}) ({"C" 3.0} {"D" 4.0}))
如果我想要一个类似输出的哈希映射列表,这是Clojure中惯用的方式吗

没有


请参阅。

谢谢dAni。我喜欢Python的列表理解。
(->> "your-file.txt" slurp (re-seq #"\w+")
     (map read-string) (apply hash-map))
(for [line ["A:1 B:2" "C:3 D:4"]
      :let [pairs (clojure.string/split line #"\s")]]
  (for [[k v] (map #(clojure.string/split %1 #":") pairs)]
    (assoc {} k (Float. v))))
(({"A" 1.0} {"B" 2.0}) ({"C" 3.0} {"D" 4.0}))