简体   繁体   中英

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. I have very little experience with clojure but initially wanted to create struct called "restaurant" so that I could create multiple instances of it. I read that structs in clojure are deprecated so to use records instead. 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.

As the comments explain, you have to get to grips with the immutable nature of the native Clojure data structures. You should not be using doseq - which works by side effects - for your fundamental algorithms.

The relevance attribute is not a property of 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 . 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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