我有一个程序可以搜索亚马逊并返回指定图书的信息。一旦完成所有搜索,我希望能够按SalesRank对书籍进行排序。我遇到的问题是能够将矢量组合成一个大型集合。现在我可以让它们逐个打印,但每次迭代都会覆盖前一个。我是一个函数式编程NOOB,所以任何帮助都表示赞赏。以下是一个片段:
(defn get_title_and_rank_for_one_isbn [isbn]
(def book_title (get-in (amazon_search isbn)[:items 0 :item-atributes :title]))
(def sales_rank(get-in (amazon_search isbn)[:items 0 :SalesRank]))
(def book_isbn(get-in (amazon_search isbn)[:items 0 :asin]))
)
(defn get_title_and_rank_for_all_isbns [list_of_isbns]
(doseq [isbn list_of_isbns]
(Thread/sleep 3000)
(get_title_and_rank_for_one_isbn isbn)
(def combine_attributes(reduce into [[book_title] [book_isbn] [sales_rank]]))
(println combine_attributes)
)
)
答案 0 :(得分:0)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<a href="javascript:void(0)"
data-href="placehold.it/1x1"
title="placehold.it">placehold.it</a>
<script>
document.querySelector("a").onclick = function(e) {
e.preventDefault();
var request = fetch(location.protocol + "//" + this.dataset.href);
request.then(response => response.blob())
.then(blob => console.log(blob))
}
</script>
</body>
</html>
可能有几种方法可以做到这一点,但这只需要一些简化的代码。您可以像这样调用函数:(defn- get-books [data]
(letfn [(one-book [book]
(let [title (get-in book :title)
rank (get-in book :rank)
isbn (get-in book :isbn)]
{:title title
:rank rank
:isbn isbn}))]
(map one-book data))))
其中(println (get-books data))
是您的json结构。
那么data
发生了什么? get-books
允许您定义可以在此处封装的函数。 Clojure函数将返回最后定义的东西,在这种情况下,它是leftn
函数。事实上,它几乎是唯一“运行”的东西。它通过map
函数映射您的数据,该函数使用one-book
创建在每本书通过函数时重新绑定的绑定。这取代了您使用let
。
同样,def
返回其最后一个定义,即键值结构。您可以映射所有数据,然后将其打印出来,将其传递给另一个函数,或者您需要执行的任何操作。
这不是一个确切的解决方案,而是建议如何考虑处理数据以及如何从函数返回值。
答案 1 :(得分:0)
首先观察(amazon_search isbn)
每个isbn只运行一次。
然后map独立地搜索每个搜索结果,并将所需数据提取到最终按销售排名排序的新地图中。
(defn get-book [isbn]
(let [itm (get-in (amazon_search isbn) [:items 0])]
{:book/title (get-in itm [:item-attributes :title])
:book/sales-rank (:SalesRank itm)
:book/isbn (:asim itm)}))
(defn get-books-sorted-by-sales-rank [isbns]
(->> isbns (map get-book) (sort-by :book/sales-rank)))
;; a bit more performant