From 3f1a24bfe3cca61eff1e87d7e40c65f31c12120a Mon Sep 17 00:00:00 2001 From: han semaj Date: Sun, 17 Aug 2014 14:53:57 +1200 Subject: [PATCH] Implement interleave and interpose --- docs/language/core.rst | 40 ++++++++++++++++++++++++++++++++++++++ hy/core/language.hy | 12 ++++++++++-- tests/native_tests/core.hy | 27 +++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/docs/language/core.rst b/docs/language/core.rst index 42070cf..e0785a0 100644 --- a/docs/language/core.rst +++ b/docs/language/core.rst @@ -290,6 +290,46 @@ either ``int`` or ``long``. For Python 3, this is ``int``. False +.. _interleave-fn: + +interleave +---------- + +.. versionadded:: 0.10.1 + +Usage: ``(interleave seq1 seq2 ...)`` + +Return an iterable of the first item in each of the sequences, then the second etc. + +.. code-block:: hy + + => (list (interleave (range 5) (range 100 105))) + [0, 100, 1, 101, 2, 102, 3, 103, 4, 104] + + => (list (interleave (range 1000000) "abc")) + [0, 'a', 1, 'b', 2, 'c'] + + +.. _interpose-fn: + +interpose +--------- + +.. versionadded:: 0.10.1 + +Usage: ``(interpose item seq)`` + +Return an iterable of the elements of the sequence separated by the item. + +.. code-block:: hy + + => (list (interpose "!" "abcd")) + ['a', '!', 'b', '!', 'c', '!', 'd'] + + => (list (interpose -1 (range 5))) + [0, -1, 1, -1, 2, -1, 3, -1, 4] + + .. _iterable?-fn: iterable? diff --git a/hy/core/language.hy b/hy/core/language.hy index d7ee3ec..e74bc8a 100644 --- a/hy/core/language.hy +++ b/hy/core/language.hy @@ -209,6 +209,14 @@ (catch [e ValueError] False) (catch [e TypeError] False))) +(defn interleave [&rest seqs] + "Return an iterable of the first item in each of seqs, then the second etc." + (itertools.chain.from_iterable (apply zip seqs))) + +(defn interpose [item seq] + "Return an iterable of the elements of seq separated by item" + (drop 1 (interleave (itertools.repeat item) seq))) + (defn iterable? [x] "Return true if x is iterable" (isinstance x collections.Iterable)) @@ -329,8 +337,8 @@ (def *exports* '[butlast calling-module-name coll? cons cons? cycle dec distinct disassemble drop drop-while empty? even? every? first filter filterfalse flatten float? gensym identity - inc input instance? integer integer? integer-char? - iterable? iterate iterator? keyword? list* + inc input instance? integer integer? integer-char? interleave + interpose iterable? iterate iterator? keyword? list* macroexpand macroexpand-1 map neg? nil? none? nth numeric? odd? pos? range remove repeat repeatedly rest reduce second some string string? take take-nth diff --git a/tests/native_tests/core.hy b/tests/native_tests/core.hy index 3a3239a..a4042b6 100644 --- a/tests/native_tests/core.hy +++ b/tests/native_tests/core.hy @@ -266,6 +266,33 @@ (assert-false (integer-char? "foo")) (assert-false (integer-char? None))) +(defn test-interleave [] + "NATIVE: testing the interleave function" + ;; with more than 2 sequences + (assert-equal (list (take 9 (interleave (range 10) + (range 10 20) + (range 20 30)))) + [0 10 20 1 11 21 2 12 22]) + ;; with sequences of different length + (assert-equal (list (interleave (range 1000000) + (range 0 -3 -1))) + [0 0 1 -1 2 -2]) + ;; with infinite sequences + (import itertools) + (assert-equal (list (take 10 (interleave (itertools.count) + (itertools.count 100)))) + [0 100 1 101 2 102 3 103 4 104])) + +(defn test-interpose [] + "NATIVE: testing the interpose function" + ;; with a list + (assert-equal (list (interpose "!" ["a" "b" "c"])) + ["a" "!" "b" "!" "c"]) + ;; with an infinite sequence + (import itertools) + (assert-equal (list (take 7 (interpose -1 (itertools.count)))) + [0 -1 1 -1 2 -1 3])) + (defn test-iterable [] "NATIVE: testing iterable? function" ;; should work for a string