fork(1) download
  1. (ns grep-n)
  2. (use 'clojure.test)
  3.  
  4. (defn grep-n [n f coll]
  5. (lazy-seq
  6. (when-let [s (seq coll)]
  7. (let [p (take-while (complement f) (take n s))
  8. n-till-first-match (count p)
  9. matches (take-while f (nthrest s n-till-first-match))]
  10. (if (seq matches)
  11. (let [n-till-last-match (+ (count p) (count matches))
  12. a (take n (nthrest s n-till-last-match))]
  13. (if (some f a)
  14. (concat p matches (grep-n n f (nthrest s n-till-last-match)))
  15. (concat p matches a (grep-n n f (nthrest s (+ n-till-last-match (count a)))))))
  16. (grep-n n f (rest s)))))))
  17.  
  18. (deftest grep-n-test
  19. (is (= '(0 1 2)
  20. (grep-n 1 #{1} (range 10))))
  21.  
  22. (is (= '(2 3 4)
  23. (grep-n 1 #{3} (range 10))))
  24.  
  25. (is (= '(4 5 6 7 8)
  26. (grep-n 2 #{6} (range 10))))
  27.  
  28. (is (= '(3 4 5 6 7 12 13 14 15 16)
  29. (grep-n 2 #{5 14} (range 20))))
  30.  
  31. (is (= '(0 1 2 3 4 5 6 7 8)
  32. (grep-n 3 #{3 5} (range 10))))
  33.  
  34. (is (= '(4 5 6)
  35. (grep-n 2 #{4} (range 4 10))))
  36.  
  37. (is (= '(3 4 5 6 7)
  38. (grep-n 2 #(= 0 (mod % 5)) (range 1 10)))))
  39.  
  40. (run-tests)
  41.  
  42. (time (doall (take 10 (grep-n 2 #{1 1111 1111111} (range 100000000)))))
Success #stdin #stdout 2.22s 130548KB
stdin
Standard input is empty
stdout
Testing grep-n

Ran 1 tests containing 7 assertions.
0 failures, 0 errors.
"Elapsed time: 680.085665 msecs"