从较小的流创建无限流

时间:2016-05-10 12:03:10

标签: clojure

我有简单的HTML网站,其中包含我要解析的表格行。这些表有不定式(或关闭)页面,即页面http://example.com/?page=1上有表格,页面http://example.com/?page=2有下一个表格。

我已经有了基本功能,如:

(defn next-page [link] ...) ; given http://example.com/?page=2 returns http://example.com/?page=3
(defn parse [link] ...) ; return list of rows from table parsed from HTML

现在我想写一个函数,它接受起始链接并创建所有行的无限流 - 首先来自给定链接,然后是下一个链接。

示例:

table on site: http://example.com/?page=2
|--------------------|
|   table 2          |
|--------------------|
| row1: value21      |
| row2: value22      |
| row3: value23      |
|--------------------|
(deftest should-parse
    (is (=
        '(value21 value22 value23)
        (parse "http://example.com/?page=2"))))

table on site: http://example.com/?page=3
|--------------------|
|   table 3          |
|--------------------|
| row1: value31      |
| row2: value32      |
|--------------------|

这应该是真的:

(defntest should-return-stream-with-rows
    (is (=
        '(value21 value22 value23 value31 value32)
        (take 5 (row-stream "http://example.com/?page=2")))))

1 个答案:

答案 0 :(得分:3)

如果我理解你,你可以使用mapcat + iterate

让我们的功能完全像你的那样(我猜)

(defn next-page [page-id] (inc page-id))

(defn parse [page-id]
  (map #(str "link-" page-id "-" %)
       (take (rand-int 10) (range))))

;; this one makes a random number of links:
;; (parse 0) => ("link-0-0" "link-0-1" "link-0-2" "link-0-3")

所以你可以使用这样的模型你想要的序列:

(defn all-links [starting-page-id]
  (mapcat parse
          (take-while some? (iterate next-page starting-page-id))))

它迭代所有next-page结果与第一页的结果,然后连接所有结果。请注意,只要next-page返回nil,就会停止迭代(感谢take-while)。

在repl中:

user> (take 20 (all-links 0))
("link-0-0" "link-0-1" "link-0-2" "link-0-3" "link-0-4" 
 "link-0-5" "link-1-0" "link-1-1" "link-2-0" "link-2-1" 
 "link-2-2" "link-3-0" "link-3-1" "link-3-2" "link-3-3" 
 "link-3-4" "link-3-5" "link-3-6" "link-3-7" "link-4-0")