简体   繁体   English

在Clojure中循环浏览多个地图

[英]Looping through multiple maps in clojure

Ello friends, 埃洛朋友们,

I feel awfully silly for asking this... but, after struggling with this issue for some time now I've decided that another pair of eyes may help to illuminate my issue. 我问这个问题真是愚蠢……但是,在为这个问题苦苦挣扎了一段时间之后,我已经决定另一双眼睛可能有助于阐明我的问题。

I'm trying to loop through two records and one map (I could possibly rewrite the map to be a record as well, but I have no need) simultaneously, compare some entries, and change values if the entries match. 我试图同时遍历两条记录和一张地图(我也可以将地图重写为一条记录,但是我没有必要),同时比较一些条目,如果条目匹配,则更改值。 What I have is similar to this: 我所拥有的与此类似:

EDIT: Here's an attempt to specifically describe what I'm doing. 编辑:这是尝试专门描述我在做什么。 However, now that I think about it perhaps this isn't the best way to go about it. 但是,现在我考虑一下,也许这不是解决问题的最佳方法。

I'm attempting to create a restaurant-selection inference engine for an AI course using clojure. 我正在尝试使用clojure为AI课程创建一个餐厅选择推理引擎。 I have very little experience with clojure but initially wanted to create struct called "restaurant" so that I could create multiple instances of it. 我对clojure的经验很少,但最初想创建一个名为“ restaurant”的结构,以便可以创建它的多个实例。 I read that structs in clojure are deprecated so to use records instead. 我读到Clojure中的结构已被弃用,因此可以改用记录。 Both the restaurants that are read in from the text file and the user input are stored as 'restaurant' records. 从文本文件中读取的餐馆和用户输入都存储为“餐馆”记录。

I read in, from a previously sorted text file database, attributes of the restaurants in question (name, type of cuisine, rating, location, price, etc..) and then put them into a vector. 我从以前排序的文本文件数据库中读取了有问题的餐厅的属性(名称,美食类型,等级,位置,价格等),然后将它们放入向量中。

Each attribute has a weight associated with it so that when the user enters search criteria the restaurants can be sorted in order of most to least relevant based on what is most likely to be the most heavily weighted items (for example, the restaurant name is the most important item, followed by type of cuisine, then the rating, etc..). 每个属性都有一个与之相关的权重,因此当用户输入搜索条件时,可以根据最可能是权重最高的商品(例如,餐馆名称是最重要的项目,其次是美食的类型,然后是评分等。) The record therefore also has a 'relevance' attribute. 因此,记录还具有“相关性”属性。

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

So the idea is that each restaurant is iterated though and the attribute values are compared to the user's input values. 因此,我们的想法是迭代每个餐厅,并将属性值与用户的输入值进行比较。 If there is a match then the local relevance-value variable get added to it the associated weight value. 如果存在匹配项,则将本地相关性值变量添加到其关联的权重值。 After which it is put into a vector, sorted, and returned. 之后,将其放入向量中,进行排序并返回。 The results can then be displayed to the user. 然后可以将结果显示给用户。 Ideally the example in -main would print the name of the most relevant restaurant. 理想情况下,-main中的示例将打印最相关的餐厅的名称。

As the comments explain, you have to get to grips with the immutable nature of the native Clojure data structures. 正如评论所解释的,您必须掌握本机Clojure数据结构的不变性。 You should not be using doseq - which works by side effects - for your fundamental algorithms. 您不应该在基本算法中使用doseq副作用的doseq

The relevance attribute is not a property of Restaurant . relevance属性不是 Restaurant的属性。 What you want is to construct a map from restaurant to relevance, for some mode of calculating relevance. 您想要的是构建从餐厅到相关性的地图,以某种方式计算相关性。 You then want to sort this map by value . 然后,您想按值对该映射进行排序。 The standard sorted-map will not do this - it sorts by key . 标准sorted-map不会执行此操作-它通过key进行排序。 You could sort the map entries thus, but there is a ready made priority map that will give you the result you require automatically. 您可以对映射条目进行排序,但是有一个现成的优先级映射 ,它将自动为您提供所需的结果。

You also have to decide how to identify restaurants, as with a database. 您还必须决定如何识别餐厅,就像使用数据库一样。 If resturant-name s are unique, they will do. 如果resturant-name是唯一的,则它们将起作用。 If not, you may be better with an artificial identifier, such as a number. 如果不是这样,使用人工标识符(例如数字)可能会更好。 You can use these as keys to a map of restaurants and the maps of relevene you onstruct to order. 您可以将它们用作餐厅地图和您要订购的Relevene地图的键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM