Click here to make these examples interactive with ClojureScript.

# gadjett.collections

### =without-keys?

`(=without-keys? obj-a obj-b keys-list)`

Compare two maps exclusing some keys

```
(=without-keys? {:a 1 :b 2 :c 3} {:a 1 :b 5} #{:b :c})
```

### append-cyclic

`(append-cyclic lst a)`

Appends an element to a list popping out the first element.

```
(-> (repeat 3 nil)
(append-cyclic 1)
(append-cyclic 2)
(append-cyclic 3)
(append-cyclic 4))
```

### assoc-cyclic

`(assoc-cyclic coll k v)`

`(assoc-cyclic coll k v n)`

Assoc a key-value pair to a map popping out an element of the map. If the key already exists, no element is popped out. If `n`

is supplied, no elmement is popped out if the map has less than `n`

entries.

```
(-> {:a 1 :b 2 :c 3}
(assoc-cyclic :d 4)
(assoc-cyclic :e 5)
(assoc-cyclic :f 6)
(assoc-cyclic :g 7))
```

### branches-and-leaves

`(branches-and-leaves m)`

Returns all branches and leaves off a nested map object.

```
(branches-and-leaves {:a {:b 1 :c {:d 2}} :e 3})
```

### collify

`(collify s)`

Ensure `s`

is a collection: if `s`

is a collection returns it; otherwise returns (s)

```
(collify 1)
```

```
(collify [1 2 3])
```

### compactize-map

`(compactize-map m)`

Removes entries with `nil`

values.

```
(compactize-map {:a 1 :b nil :c 3})
```

### compactize-map-recursive

`(compactize-map-recursive m)`

Remove from a map the entries whose values are `nil`

. If all the values of a nested map are `nil`

the entrie is removed.

(compactize-map-recursive {:x 1 :z {:a nil} :a {:b nil :c 2 :d {:e nil :f 2}}})

### deep-merge

`(deep-merge & maps)`

Deep merges maps.

```
(deep-merge {} {:a {:b 1}, :c {:e 4, :d 2, :f {:g 8}}} {:a {:b 1}, :c {:e 4, :d 2000, :f {:g 9000}}})
```

### deep-merge-with

`(deep-merge-with g & maps)`

Like merge-with but deep.

```
(deep-merge-with concat
{:x {:b [1]
:a [1]}}
{:x {:a [3 4]}})
```

### dissoc-in

`(dissoc-in m [k & ks :as keys])`

Dissociates an entry from a nested associative structure returning a new nested structure. `keys`

is a sequence of keys. Any empty maps that result will not be present in the new structure. See assoc-in

```
(dissoc-in {:a 1 :b 2} [:b])
```

```
(dissoc-in {:a {:b 2 :B 3} :c 3} [:a :b])
```

```
(dissoc-in {:a {:b 2} :c 3} [:a :b])
```

### edn-zip

`(edn-zip root)`

A zipper for `edn`

.

```
(edn-zip {:a {:b 1}, :c {:e 4, :d 2, :f {:g 8}}})
```

### filter-branches

`(filter-branches m p)`

Filters branches of a (nested) map `m`

according to a predicate `m`

.

```
(filter-branches {:x {:id 19 :b 1 :c {:id 2}} :e 3} :id)
```

### filter-map

`(filter-map f m)`

Run a function on the values of a map and keep only the (key, value) pairs for which the function returns true

```
(filter-map even? {:a 1 :b 2 :c 3})
```

### fix-blank-lines

`(fix-blank-lines s)`

Removes blank lines from the begining and from the end (not from the middle)

```
; we use (char 10) for end-of-line due to technical issues with string manipulation with `codox`
(let [lines (clojure.string/join (char 10) [" ", "aa", " ", "bb", " "])]
(fix-blank-lines lines))
```

### flatten-keys

`(flatten-keys m)`

Flatten the keys of a nested map. Thanks to Jay Fields

```
(flatten-keys {:a {:b 1} :c {:d 2 :e 4 :f {:g 8}}})
```

### index-of

`(index-of s element)`

Returns the index of an element in a sequence or `-1`

if not present.

```
(index-of (range 100) 18)
```

### join-them

`(join-them fns colls)`

Join a sequence of collections `colls`

according to function equality. `fns`

- a sequence of functions `colls`

- a sequence of collections

```
(let [a [{:id 1 :price 19} {:id 2 :price 3}]
b [{:guid 1 :quantity 13}]]
(join-them [:id :guid] [a b]))
```

### map-2d-vec

`(map-2d-vec f m)`

Maps the values of a `2D`

vector where each element of the vector is a key-value pair. `f`

is a `1-ary`

function that receives the key.

```
(map-2d-vec inc [[:a 1] [:b 2]])
```

### map-2d-vec-kv

`(map-2d-vec-kv fk fv m)`

Maps the values of a `2D`

vector where each element of the vector is a key-value pair. `fk`

is a `1-ary`

function that receives the key. `fv`

is a `1-ary`

function that receives the value.

```
(map-2d-vec-kv name inc [[:a 1] [:b 2]])
```

### map-nested-vals

`(map-nested-vals f m)`

Map the values of a nested map.

```
(map-nested-vals first {:a [1 2 3]
:b {:c [4 5 6]}})
```

### map-object

`(map-object f m)`

Returns a map with the same keys as `m`

and with the values transformed by `f`

. `f`

is a `1-ary`

function that receives the key.

```
(map-object inc {:a 1 :b 2 :c 3})
```

### map-object-kv

`(map-object-kv fk fv m)`

Returns a map with the keys mapped by `fk`

and the values mapped by `fv`

.

```
(map-object-kv name inc {:a 1 :b 2 :c 3})
```

### map-object-with-key

`(map-object-with-key f m)`

Returns a map with the same keys as `m`

and with the values transformed by `f`

. `f`

must be a `2-ary`

function that receives the key and the value as arguments.

```
(map-object-with-key list {:a 1 :b 2 :c 3})
```

### map-reverse-hierarchy

`(map-reverse-hierarchy m)`

Turns a hash map inside out. See: here

```
(map-reverse-hierarchy {:monday {:banana 2 :apple 3}
:tuesday {:banana 5 :orange 2}})
```

### map-to-object

`(map-to-object f lst)`

Returns a map whose keys are the elements of `lst`

and values are mapped by `f`

.

```
(map-to-object inc (range 5))
```

### map-with-index

`(map-with-index s idx-key val-key)`

Maps a sequence to a sequence of maps with index and value

```
(map-with-index [10 20 30] :idx :val)
```

### mapify

`(mapify f s)`

Takes a seq, and returns a map where the keys are the result of applying f to the elements in the seq. The result of f should be unique for each element in the seq, otherwise you will loose some data. If it is not unique, consider using group-by.

```
(mapify inc (range 5) )
```

### max-and-min

`(max-and-min x)`

Returns a couple of the `max`

and the `min`

of a sequence.

```
(max-and-min (range 5))
```

### mean

`(mean x)`

Calculates the mean (a.k.a average) of a sequence of numbers.

```
(mean [1 2 10 -1 12.3])
```

### my-replace

`(my-replace smap form)`

Recursively transforms `form`

by replacing keys in `smap`

with their values, spliced. The values in `smap`

must be sequences. Like clojure.walk/prewalk-replace but supports list in values.

```
(my-replace '{go (go gadjett)} '(go (<! (timeout 100)) (go (<! timeout 0))))
```

### nearest-of-seq

`(nearest-of-seq a b)`

Maps each element of `b`

to its nearest element in `a`

. If `a`

is empty, returns `b`

.

```
(nearest-of-seq (range 5) [1.2 3.4 4])
```

### nearest-of-ss

`(nearest-of-ss ss x)`

Returns the nearest number to `x`

of a sorted set

```
(nearest-of-ss (apply sorted-set (range 5)) 1.2)
```

### out-of-bound?

`(out-of-bound? v idx)`

Checks if index `idx`

is in range of vector `v`

. More efficient than `(get v idx)`

```
(map #(out-of-bound? [1 2 3] %) [-1 0 1 2 3 4])
```

### partition-between

`(partition-between pred coll)`

Splits a collection between two items according to predicate `pred`

- which means split the sequence on breaking point.

See: here

For instance, split each time the series stop being ascending:

```
(partition-between > [1 2 4 9 8 7 6 5 1 2 4 5 11])
```

### positions

`(positions coll-of-lengths & {:keys [max-val first-val], :or {max-val infinity, first-val 0}})`

Receives a collection of lengths and returns a list of start and end positions. Options: * `max-val`

: (default `infinity`

) - max value for `end`

* `first-val`

: (default 0) - first value of `start`

```
(positions '(10 10 20) :first-val 100 :max-val 137)
```

### range-till-end

`(range-till-end & args)`

Like `range`

but including the `end`

.

```
(range-till-end 10)
```

```
(range-till-end 10 18)
```

```
(range-till-end 10 100 5)
```

### remove-blank-lines

`(remove-blank-lines s)`

Removes blank lines.

```
; we use (char 10) for end-of-line due to technical issues with string manipulation with `codox`
(let [lines (clojure.string/join (char 10) [" ", "aa", " ", "bb", " "])]
(remove-blank-lines lines))
```

### remove-ending-comments

`(remove-ending-comments s)`

Removes comment lines from the end.

```
; we use (char 10) for end-of-line due to technical issues with string manipulation with `codox`
(let [lines (clojure.string/join (char 10) ["aa", " ", "bb" "; this comment should not appear"])]
(remove-ending-comments lines))
```

### sequence->map

`(sequence->map s)`

Converts a sequence into a map where the keys are the indexes of the elements in the sequence.

```
(sequence->map [10 20 30])
```

### sequence-of-maps->map

`(sequence-of-maps->map coll key-fn val-fn)`

Converts a sequence of maps into a map where:

- the keys are extracted from the maps using
`key-fn`

- the vals extracted from the maps using
`val-fn`

```
(sequence-of-maps->map [{:key :price :value 19}
{:key :quantity :value 100}]
:key :value)
```

### split-by-predicate

`(split-by-predicate coll pred n)`

Splits a collection to items where the separator is a repetition of at least n elements that satisfy `pred`

.

Inspired by: this question.

```
(split-by-predicate (shuffle (range 30)) even? 2)
```

### split-by-predicate-positions

`(split-by-predicate-positions coll pred n d)`

Optimized version of `split-by-predicate`

where we assume that the data is from a signal that we can sample.

Instead of checking each element, we check 1 over `n`

elements.

We return the positions where the data splits.

```
(let [data (map Math/sin (range 0 6.28 0.001))]
(split-by-predicate-positions data #(<= -0.01 % 0.01) 2 10))
```

The following assertion holds:

```
(= (split-by-predicate coll pred n)
(map #(apply subsequence data %) (split-by-predicate-positions coll pred n 1)))
```

Here is an example:

```
(let [data (map Math/sin (range 0 6.28 0.01))]
(= (split-by-predicate data #(<= -0.01 % 0.01) 2)
(map #(apply subsequence data %) (split-by-predicate-positions data #(<= -0.01 % 0.01) 2 1))))
```

### submap?

`(submap? m1 m2)`

Checks if `m1`

is a submap of `m2`

. Map `m1`

is a submap of `m2`

if all key/value pairs in `m1`

exist in `m2`

.

```
(submap? {:a 1} {:a 1 :b 2})
```

```
(submap? {:a 1} {:a 1 :b 2 :c nil})
```

### subsequence

`(subsequence coll start end)`

Returns a lazy subsequence of `coll`

, starting at `start, ending at`

end` (not included).

```
(subsequence (range) 10 20)
```

### substr

`(substr s start)`

`(substr s start end)`

Like clojure.core/subs but prevents some exceptions when the `start`

or `end`

are out of bound.

```
(subs "" -2)
```

### take-from-map

`(take-from-map n m)`

Creates a map with n leaves which are nested values of m. The following assertion holds:

```
(>= n (count (flatten-keys (take-from-map n m)))))))
```

```
(take-from-map 3 {:a {:b 1}, :c {:e 4, :d 2, :f {:g 8}}})
```

### unflatten-keys

`(unflatten-keys m)`

Unflattend the keys of a map that has been `flatten-keys`

ed.

```
(unflatten-keys {[:a :b] 1, [:c :d] 2, [:c :e] 4, [:c :f :g] 8})
```