into

added
1.0

ns
clojure.core

type
function

(into) (into to) (into to from) (into to xform from)

Returns a new coll consisting of to-coll with all of the items of
from-coll conjoined. A transducer may be supplied.

                ; Maps can be constructed from a sequence of 2-vectors or a sequence 
; of maps
user=> (into (sorted-map) [ [:a 1] [:c 3] [:b 2] ] )
{:a 1, :b 2, :c 3}
user=> (into (sorted-map) [ {:a 1} {:c 3} {:b 2} ] )
{:a 1, :b 2, :c 3}

; When maps are the input source, they convert into an unordered sequence 
; of key-value pairs, encoded as 2-vectors
user=> (into [] {1 2, 3 4})
[[1 2] [3 4]]

            
                ; Items are conj'ed one at a time, which puts them at the head of 
; the destination list
user=> (into () '(1 2 3))
(3 2 1)

; This does not happen for a vector, however, due to the behavior of conj:
user=> (into [1 2 3] '(4 5 6))
[1 2 3 4 5 6]

            
                (defn test-key-inclusion-cols
  "return all values in column1 that aren't in column2"
  [column1 column2]
  (filter (complement (into #{} column2)) column1))

            
                ; Change from one type of map to another
user=> (into (sorted-map) {:b 2 :c 3 :a 1})
{:a 1, :b 2, :c 3}
            
                ; Convert a nested ordering map to hash-map (or another)
user=> (use 'flatland.ordered.map)
user=> (def ord-map (ordered-map :a "a" :b "b" :c {:d "d" :e "e"}))
user=> ord-map
#ordered/map ([:a "a"] [:b "b"] [:c {:d "d", :e "e"}]) 

user=> (use 'clojure.walk)
user=> (defn disorder [ordering-map map-fn] 
  (postwalk #(if (map? %) (into map-fn %) %) ordering-map))

user=> (disorder ord-map {})
{:a "a", :b "b", :c {:d "d", :e "e"}}
            
                ;impl apply merge
user=> (into {:x 4} [{:a 1} {:b 2} {:c 3}])

{:x 4, :a 1, :b 2, :c 3}
            
                ;; How do we use a transducer?

; Define the transducer with `comp` but in `->` order:
(def xform (comp (map #(+ 2 %))
                 (filter odd?)))
; adds 2, then omits if result is even.

(into [-1 -2] xform (range 10))
; => [-1 -2 3 5 7 9 11]


; Alternatively, using `transduce` directly:
(transduce xform conj [-1 -2] (range 10))
; => [-1 -2 3 5 7 9 11]

; Alternatively, using reduce and explicitly calling `map` and `filter`:
(reduce conj [-1 -2] (->> (range 10)
                          (map #(+ 2 %))
                          (filter odd?)))
; => [-1 -2 3 5 7 9 11]


;; Let's benchmark, using Criterium (https://github.com/hugoduncan/criterium)
(require '[criterium.core :refer [quick-bench]])
(quick-bench (into [-1 -2] xform (range 1000000)))
;   Execution time lower quantile : 54.368948 ms ( 2.5%)
;   Execution time upper quantile : 55.976303 ms (97.5%)

(quick-bench (transduce xform conj [-1 -2] (range 1000000)))
;   Execution time lower quantile : 77.738505 ms ( 2.5%)
;   Execution time upper quantile : 87.088016 ms (97.5%): 1.5x slower than into

(quick-bench (reduce conj [-1 -2] (->> (range 1000000) 
                                       (map #(+ 2 %))
                                       (filter odd?))))
;   Execution time lower quantile : 92.607522 ms ( 2.5%)
;   Execution time upper quantile : 100.426780 ms (97.5%): 1.8x slower than into
            
                ;; Interesting case you can't directly convert list or sequence into map (due performance reasons). One should use vector instead.

;; This is ok:
(into {} [[:a "a"] [:b "b"]])
;;=> {:a "a", :b "b"}

;; But this isn't:
(into {} ['(:a "a") '(:b "b")])
;;=> ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)