001 (ns sparse-array.extract
002 (:require [sparse-array.core :refer :all]))
003
004 ;;; The whole point of working with sparse arrays is to work with interesting
005 ;;; subsets of arrays most of which are uninteresting. To extract an
006 ;;; interesting subset from an array, we're going to need an extract function.
007
008 (defn- extract-from-sparse
009 "Return a subset of this sparse `array` comprising all those cells for which
010 this `function` returns a 'truthy' value."
011 [array function]
012 (reduce
013 merge
014 (apply
015 make-sparse-array
016 (cons
017 (:coord array)
018 (if (coll? (:content array)) (:content array))))
019 (map
020 #(if
021 (= :data (:content array))
022 (if (function (array %)) {% (array %)})
023 (let [v (extract-from-sparse (array %) function)]
024 (if
025 (empty?
026 (filter integer? (keys v)))
027 nil
028 {% v})))
029 (filter integer? (keys array)))))
030
031 (defn extract-from-dense
032 "Return a subset of this dense `array` comprising all those cells for which
033 this `function` returns a 'truthy' value. Use these `axes` if provided."
034 ([array function]
035 (extract-from-dense array function (map #(keyword (str "i" %)) (range))))
036 ([array function axes]
037 (let
038 [dimensions (dense-dimensions array)]
039 (reduce
040 merge
041 (apply make-sparse-array (take dimensions axes))
042 (if
043 (= dimensions 1)
044 (map
045 (fn [i v] (if (function v) (hash-map i v)))
046 (range)
047 array)
048 (map
049 (fn [i v] (if (empty? (filter integer? (keys v))) nil (hash-map i v)))
050 (range)
051 (map #(extract-from-dense % function (rest axes)) array)))))))
052
053 (defn extract
054 "Return a sparse subset of this `array` - which may be either sparse or
055 dense - comprising all those cells for which this `function` returns a
056 'truthy' value."
057 [array function]
058 (cond
059 (sparse-array? array)
060 (extract-from-sparse array function)
061 (dense-array? array)
062 (extract-from-dense array function)
063 *safe-sparse-operations*
064 (throw
065 (ex-info
066 "Argument passed as `array` is neither sparse nor dense."
067 {:array array}))))
068