added remaining itertools

Some names have been changed.
Removed redundant zipwith.
Made `first` and `last` more efficient.
This commit is contained in:
gilch 2015-09-03 11:45:55 -06:00
parent cdd60ce77d
commit 6f93de68d7
3 changed files with 86 additions and 75 deletions

View File

@ -1237,21 +1237,3 @@ Returns an iterator from *coll* as long as *pred* returns ``True``.
=> (list (take-while neg? [ 1 2 3 -4 5])) => (list (take-while neg? [ 1 2 3 -4 5]))
[] []
.. _zipwith-fn:
zipwith
-------
.. versionadded:: 0.9.13
Usage: ``(zipwith fn coll ...)``
Equivalent to ``zip``, but uses a multi-argument function instead of creating
a tuple. If ``zipwith`` is called with N collections, then *fn* must accept
N arguments.
.. code-block:: hy
=> (import operator)
=> (list (zipwith operator.add [1 2 3] [4 5 6]))
[5, 7, 9]

View File

@ -27,6 +27,7 @@
(import functools) (import functools)
(import collections) (import collections)
(import [fractions [Fraction :as fraction]]) (import [fractions [Fraction :as fraction]])
(import operator) ; shadow not available yet
(import sys) (import sys)
(if-python2 (if-python2
(import [StringIO [StringIO]]) (import [StringIO [StringIO]])
@ -91,41 +92,74 @@
(.add seen val)))))) (.add seen val))))))
(if-python2 (if-python2
(do (def
(setv filterfalse itertools.ifilterfalse) filterfalse itertools.ifilterfalse
(setv zip_longest itertools.izip_longest) zip-longest itertools.izip_longest
(setv filter itertools.ifilter) ;; not builtin in Python3
(setv map itertools.imap) reduce reduce
(setv zip itertools.izip) ;; hy is more like Python3
(setv range xrange) filter itertools.ifilter
(setv input raw_input) input raw_input
(setv reduce reduce)) map itertools.imap
(do range xrange
(setv reduce functools.reduce) zip itertools.izip)
(setv filterfalse itertools.filterfalse) (def
(setv zip_longest itertools.zip_longest) filterfalse itertools.filterfalse
; Someone can import these directly from `hy.core.language`; zip-longest itertools.zip_longest
; we'll make some duplicates. ;; was builtin in Python2
(setv filter filter) reduce functools.reduce
(setv map map) ;; Someone can import these directly from `hy.core.language`;
(setv zip zip) ;; we'll make some duplicates.
(setv range range) filter filter
(setv input input))) input input
map map
range range
zip zip))
(setv cycle itertools.cycle) ;; infinite iterators
(setv repeat itertools.repeat) (def
(setv drop-while itertools.dropwhile) count itertools.count
(setv take-while itertools.takewhile) cycle itertools.cycle
(setv zipwith map) repeat itertools.repeat)
(setv remove filterfalse)
;; shortest-terminating iterators
(def
*map itertools.starmap
chain itertools.chain
compress itertools.compress
drop-while itertools.dropwhile
group-by itertools.groupby
islice itertools.islice
remove filterfalse
take-while itertools.takewhile
tee itertools.tee)
;; combinatoric iterators
(def
combinations itertools.combinations
multicombinations itertools.combinations_with_replacement
permutations itertools.permutations
product itertools.product)
;; also from itertools, but not in Python2, and without func option until 3.3
(defn accumulate [iterable &optional [func operator.add]]
"accumulate(iterable[, func]) --> accumulate object
Return series of accumulated sums (or other binary function results)."
(setv it (iter iterable)
total (next it))
(yield total)
(for* [element it]
(setv total (func total element))
(yield total)))
(defn drop [count coll] (defn drop [count coll]
"Drop `count` elements from `coll` and yield back the rest" "Drop `count` elements from `coll` and yield back the rest"
(itertools.islice coll count nil)) (islice coll count nil))
(defn drop-last [n coll] (defn drop-last [n coll]
"Return a sequence of all but the last n elements in coll." "Return a sequence of all but the last n elements in coll."
(let [[iters (itertools.tee coll)]] (let [[iters (tee coll)]]
(map first (apply zip [(get iters 0) (map first (apply zip [(get iters 0)
(drop n (get iters 1))])))) (drop n (get iters 1))]))))
@ -196,7 +230,7 @@
(defn first [coll] (defn first [coll]
"Return first item from `coll`" "Return first item from `coll`"
(nth coll 0)) (next (iter coll) nil))
(defn identity [x] (defn identity [x]
"Returns the argument unchanged" "Returns the argument unchanged"
@ -227,11 +261,11 @@
(defn interleave [&rest seqs] (defn interleave [&rest seqs]
"Return an iterable of the first item in each of seqs, then the second etc." "Return an iterable of the first item in each of seqs, then the second etc."
(itertools.chain.from_iterable (apply zip seqs))) (chain.from-iterable (apply zip seqs)))
(defn interpose [item seq] (defn interpose [item seq]
"Return an iterable of the elements of seq separated by item" "Return an iterable of the elements of seq separated by item"
(drop 1 (interleave (itertools.repeat item) seq))) (drop 1 (interleave (repeat item) seq)))
(defn iterable? [x] (defn iterable? [x]
"Return true if x is iterable" "Return true if x is iterable"
@ -249,7 +283,7 @@
(defn last [coll] (defn last [coll]
"Return last item from `coll`" "Return last item from `coll`"
(get (list coll) -1)) (get (tuple coll) -1))
(defn list* [hd &rest tl] (defn list* [hd &rest tl]
"Return a dotted list construed from the elements of the argument" "Return a dotted list construed from the elements of the argument"
@ -355,7 +389,7 @@
(defn take [count coll] (defn take [count coll]
"Take `count` elements from `coll`, or the whole set if the total "Take `count` elements from `coll`, or the whole set if the total
number of entries in `coll` is less than `count`." number of entries in `coll` is less than `count`."
(itertools.islice coll nil count)) (islice coll nil count))
(defn take-nth [n coll] (defn take-nth [n coll]
"Return every nth member of coll "Return every nth member of coll
@ -389,18 +423,10 @@
(else (if parsed (break))))) (else (if parsed (break)))))
parsed) parsed)
(defn read-str [input] (defn read-str [input]
"Reads and tokenizes first line of input" "Reads and tokenizes first line of input"
(read :from-file (StringIO input))) (read :from-file (StringIO input)))
(defn zipwith [func &rest lists]
"Zip the contents of several lists and map a function to the result"
(do
(import functools)
(map (functools.partial (fn [f args] (apply f args)) func) (apply zip lists))))
(defn hyify [text] (defn hyify [text]
"Convert text to match hy identifier" "Convert text to match hy identifier"
(.replace (string text) "_" "-")) (.replace (string text) "_" "-"))
@ -428,11 +454,13 @@
(except [] (string value)))))) (except [] (string value))))))
(def *exports* (def *exports*
'[butlast calling-module-name coll? cons cons? cycle dec distinct disassemble '[*map accumulate butlast calling-module-name chain coll? combinations
drop drop-last drop-while empty? even? every? first filter filterfalse compress cons cons? count cycle dec distinct disassemble drop drop-last
flatten float? fraction gensym identity inc input instance? integer integer? drop-while empty? even? every? first filter filterfalse flatten float?
integer-char? interleave interpose iterable? iterate iterator? keyword fraction gensym group-by identity inc input instance? integer integer?
keyword? last list* macroexpand macroexpand-1 map merge-with name neg? nil? integer-char? interleave interpose islice iterable? iterate iterator?
none? nth numeric? odd? partition pos? range read read-str remove repeat keyword keyword? last list* macroexpand macroexpand-1 map merge-with
repeatedly rest reduce second some string string? symbol? take take-nth multicombinations name neg? nil? none? nth numeric? odd? partition
take-while zero? zip zip_longest zipwith]) permutations pos? product range read read-str remove repeat repeatedly rest
reduce second some string string? symbol? take take-nth take-while tee zero?
zip zip-longest])

View File

@ -596,14 +596,6 @@
(setv res (list (take-while (fn [x] (not (none? x))) [1 2 3 4 None 5 6 None 7]))) (setv res (list (take-while (fn [x] (not (none? x))) [1 2 3 4 None 5 6 None 7])))
(assert-equal res [1 2 3 4])) (assert-equal res [1 2 3 4]))
(defn test-zipwith []
"NATIVE: testing the zipwith function"
(import operator)
(setv res (zipwith operator.add [1 2 3] [3 2 1]))
(assert-equal (list res) [4 4 4])
(setv res (zipwith operator.sub [3 7 9] [1 2 4]))
(assert-equal (list res) [2 5 5]))
(defn test-doto [] (defn test-doto []
"NATIVE: testing doto macro" "NATIVE: testing doto macro"
(setv collection []) (setv collection [])
@ -629,3 +621,12 @@
"NATIVE: testing import of __init__.hy" "NATIVE: testing import of __init__.hy"
(import tests.resources.bin) (import tests.resources.bin)
(assert (in "_null_fn_for_import_test" (dir tests.resources.bin)))) (assert (in "_null_fn_for_import_test" (dir tests.resources.bin))))
(defn test-accumulate []
"NATIVE: testing the accumulate function"
(assert-equal (list (accumulate ["a" "b" "c"]))
["a" "ab" "abc"])
(assert-equal (list (accumulate [1 2 3 4 5]))
[1 3 6 10 15])
(assert-equal (list (accumulate [1 -2 -3 -4 -5] -))
[1 3 6 10 15]))