将嵌套映射列表转换为映射的替代方法

时间:2011-10-29 20:27:00

标签: clojure

我有以下工作代码将带有嵌套地图的列表(实际上是推文数据)转换为地图:

(defn filter
  "This function returns a map with the user as key, #followers as value"
  [raw-tweets]

  (let [users (map :user raw-tweets)
        names (map :name users)
        followers (map :followers_count users)]
    (zipmap names followers)))

虽然这可以按预期工作,但我想知道在Clojure中是否会有更惯用的方法。任何替代方案?

4 个答案:

答案 0 :(得分:2)

你所拥有的很好,尽管你可以使用reduce:

来构建地图
(defn user-followers [raw-tweets]
  (reduce #(assoc %1 (:name %2) (:followers_count %2))
    {} (map :user raw-tweets)))

答案 1 :(得分:1)

我只是开始学习clojure,但我认为这种方式可能更具惯用性。无论如何,它都是另一种选择。

(defn filter
  "This function returns a map with the user as key, #followers as value"
  [raw-tweets]
  (into {} (map #(let [user (:user %)]
                   [(:name user) (:followers_count user)])
                raw-tweets)))

它使用一个函数映射原始推文,该函数检索每条推文的用户,并返回一个带有该用户名称和关注者计数的向量。 into函数接受两个序列并将第二个元素的每个元素连接到第一个元素上,这将在向量函数返回之前将向量列表转换为映射。

答案 2 :(得分:1)

我发现@ Daan的答案很好,但我会在混音中添加解构。

(defn filter-tweets
  "This function returns a map with the user as key, #followers as value"
  [raw-tweets]
  (into {} (map (fn [{{name :name follower-count :followers_count} :user}]
                  [name follower-count])
                raw-tweets)))

答案 3 :(得分:1)

我不喜欢(map (fn ...))模式 - 这只是一种写出for理解的丑陋方式。我把它写成:

(into {}
      (for [{:keys [user]} raw-tweets]
        ((juxt :name :followers_count) user)))

或者这个,对我来说感觉不那么自然,但是避免为你刚才要使用的价值创造名字。

(into {} (map (comp (juxt :name :followers_count) :user)
              raw-tweets))
相关问题