【问题标题】:Looping through multiple maps in clojure在clojure中循环遍历多个地图
【发布时间】:2016-02-22 19:02:48
【问题描述】:

朋友们,

问这个问题我觉得非常愚蠢......但是,在为这个问题挣扎了一段时间之后,我决定另一双眼睛可能有助于阐明我的问题。

我正在尝试同时循环遍历两条记录和一个映射(我也可以将映射重写为记录,但我不需要),比较一些条目,如果条目匹配则更改值。我所拥有的与此类似:

编辑:这里试图具体描述我在做什么。然而,现在我想这也许不是最好的方法。

我正在尝试使用 clojure 为 AI 课程创建餐厅选择推理引擎。我对 clojure 的经验很少,但最初想创建一个名为“restaurant”的结构,以便我可以创建它的多个实例。我读到 clojure 中的结构已被弃用,因此改为使用记录。从文本文件中读取的餐厅和用户输入都存储为“餐厅”记录。

我从之前排序的文本文件数据库中读入相关餐厅的属性(名称、菜式、评级、位置、价格等),然后将它们放入向量中。

每个属性都有一个与其关联的权重,因此当用户输入搜索条件时,可以根据最有可能是权重最高的项目(例如,餐厅名称是最重要的项目,其次是美食类型,然后是评级等。)。因此,该记录还具有“相关性”属性。

    (defrecord Restaurant [resturant-name  cuisine 
                           rating          location 
                           price           relevance])
    ;stuff
    ;stuff
    ;stuff


    (defn search
      [restaurants user-input]

    (def ordered-restaurants [])

      (doseq [restaurant restaurants]
       (let [restaurant-relevance-value 0]

        (doseq [input             user-input
                attributes        restaurant
                attribute-weight  weights]

          (cond
            (= input (val attributes))  
            (def restaurant-relevance-value (+ restaurant-relevance-value 
            (val attribute-weight)))))

    (assoc restaurant :relevance restaurant-relevance-value)
    (def ordered-restaurants (conj ordered-restaurants restaurant))))

  (def ordered-restaurants (sort-by > (:relevance ordered-restaurants)))

   ordered-restaurants)


 ;more stuff
 ;more stuff
 ;more stuff


 (defn -main
  [& args]

   (def restaurant-data (process-file "resources/ResturantDatabase.txt"))

   (let [input-values (Restaurant. "Italian" "1.0" "1.0" "$" "true"
      "Casual" "None" "1")]

    (println :resturant-name (nth (search restaurant-data input-values) 0))))

所以想法是每家餐厅都被迭代,并将属性值与用户的输入值进行比较。如果存在匹配,则将本地相关值变量添加到相关的权重值。之后将其放入向量中,排序并返回。然后可以将结果显示给用户。理想情况下,-main 中的示例将打印最相关餐厅的名称。

【问题讨论】:

  • 我在理解什么样的任务需要您同时遍历多个地图时遇到了一些麻烦,考虑到地图的迭代顺序是未定义的,除非它们已排序。你能添加一个MCVE 你到底在做什么吗?
  • do-seq 用于副作用,这很少是您想要的,当然不是在您只是从现有集合构建新集合的情况下。
  • Clojure 映射和记录是不可变的。 (assoc restaurant :relevance restaurant-relevance-value) - assoc 返回添加了 :relevance 键的新餐厅记录,返回值被忽略。

标签: foreach clojure hashmap records


【解决方案1】:

正如 cmets 所解释的,您必须掌握原生 Clojure 数据结构的不可变特性。您不应该将 doseq 用于您的基本算法 - 它会产生副作用。

relevance 属性不是Restaurant 的属性。您想要的是构建从餐厅到相关性的地图,用于某种计算相关性的模式。然后,您希望按值 对该地图进行排序。标准的 sorted-map 不会这样做 - 它按 key 排序。您可以对地图条目进行排序,但有一个现成的priority map 会自动为您提供所需的结果。

您还必须决定如何识别餐厅,就像使用数据库一样。如果resturant-names 是唯一的,他们会这样做。如果没有,您可能会更好地使用人工标识符,例如数字。您可以将它们用作餐厅地图和您指示订购的 relevene 地图的键。

【讨论】:

  • 谢谢。这说明了我所犯的一些结构性错误。你所说的doseq“通过副作用起作用”是什么意思?
  • @LucasRudd A doseq 总是返回 nil,所以它唯一的效果就是改变环境中的某些东西,通常是 var
猜你喜欢
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 2014-12-04
  • 2023-03-15
  • 2022-01-10
  • 2018-11-05
  • 1970-01-01
  • 2011-06-18
相关资源
最近更新 更多