Public Vars

Back

group-by (clj)

(source)

function

(group-by f coll)
Returns a map of the elements of coll keyed by the result of f on each element. The value at each key will be a vector of the corresponding elements, in the order they appeared in coll.

Examples

typedclojure/typedclojure
(ns ^:no-doc typed.ann.clojure
  "Type annotations for the base Clojure distribution."
  #?(:cljs (:require-macros [typed.ann-macros.clojure :as macros]))
  (:require [clojure.core :as cc]
            [typed.clojure :as t]
            #?(:clj [typed.ann-macros.clojure :as macros])
            #?(:clj typed.ann.clojure.jvm) ;; jvm annotations
            #?(:clj clojure.core.typed))
  #?(:clj
     (:import (clojure.lang PersistentHashSet PersistentList
                            APersistentMap #_IPersistentCollection
                            #_ITransientSet
                            IRef)
              (java.util Comparator Collection))))

cc/first (t/All [x] (t/IFn [(t/HSequential [x t/Any :*]) :-> x
                            :object {:id 0 :path [(Nth 0)]}]
                           [(t/EmptySeqable x) :-> nil]
                           [(t/NonEmptySeqable x) :-> x]
                           [(t/Seqable x) :-> (t/Option x)]))
cc/second (t/All [x] (t/IFn [(t/HSequential [t/Any x t/Any :*]) :-> x
                             :object {:id 0 :path [(Nth 1)]}]
                            [(t/Option (t/I (t/Seqable x) (t/CountRange 0 1))) :-> nil]
                            [(t/I (t/Seqable x) (t/CountRange 2)) :-> x]
                            [(t/Seqable x) :-> (t/Option x)]))
cc/ffirst (t/All [x] [(t/Seqable (t/Seqable x)) :-> (t/Nilable x)])
cc/nfirst (t/All [x] [(t/Seqable (t/Seqable x)) :-> (t/NilableNonEmptyASeq x)])
cc/group-by (t/All [x y] [[x :-> y] (t/Seqable x) :-> (t/Map y (t/NonEmptyAVec x))])
cc/fnext (t/All [x] [(t/Seqable x) :-> (t/Option x)])
cc/nnext (t/All [x] [(t/Seqable x) :-> (t/NilableNonEmptyASeq x)])
cc/nthnext (t/All [x] (t/IFn [nil t/AnyInteger :-> nil]
                             [(t/Seqable x) t/AnyInteger :-> (t/NilableNonEmptyASeq x)]))
cc/rest (t/All [x] [(t/Seqable x) :-> (t/ASeq x)])
cc/last (t/All [x] (t/IFn [(t/NonEmptySeqable x) :-> x]
                          [(t/Seqable x) :-> (t/U nil x)]))
cc/butlast (t/All [x] [(t/Seqable x) :-> (t/NilableNonEmptyASeq x)])
cc/next (t/All [x] (t/IFn [(t/Option (t/Coll x)) :-> (t/NilableNonEmptyASeq x)
                           :filters {:then (& (is (t/CountRange 2) 0)
                                              (! nil 0))
                                     :else (| (is (t/CountRange 0 1) 0)
                                              (is nil 0))}]
                          [(t/Seqable x) :-> (t/NilableNonEmptyASeq x)]))
ReactiveX/RxClojure
(ns rx.lang.clojure.core-test
  (:require [rx.lang.clojure.core :as rx]
            [rx.lang.clojure.blocking :as b]
            [rx.lang.clojure.future :as f]
            [clojure.test :refer [deftest is testing are]]))

(deftest test-group-by
  (let [xs [{:k :a :v 1} {:k :b :v 2} {:k :a :v 3} {:k :c :v 4}]]
    (testing "with just a key-fn"
      (is (= [[:a {:k :a :v 1}]
              [:a {:k :a :v 3}]
              [:b {:k :b :v 2}]
              [:c {:k :c :v 4}]]
             (->> xs
                  (rx/seq->o)
                  (rx/group-by :k)
                  (rx/mapcat (fn [[k vo :as me]]
                               (is (instance? clojure.lang.MapEntry me))
                               (rx/map #(vector k %) vo)))
                  (b/into [])))))

    ; TODO reinstate once this is implemented
    ; see https://github.com/Netflix/RxJava/commit/02ccc4d727a9297f14219549208757c6e0efce2a
    #_(testing "with a val-fn"
      (is (= [[:a 1]
              [:b 2]
              [:a 3]
              [:c 4]]
             (->> xs
                  (rx/seq->o)
                  (rx/group-by :k :v)
                  (rx/mapcat (fn [[k vo :as me]]
                               (is (instance? clojure.lang.MapEntry me))
                               (rx/map #(vector k %) vo)))
                  (b/into [])))))))

  ; group-by is a good way to test merge behavior without truly async code
  ; here the :a and :b observables are interleaved when merged
  (let [xs [{:k :a :v 1} {:k :b :v 2} {:k :a :v 3} {:k :c :v 4}]]
    (is (= [[:a {:k :a :v 1}]
            [:b {:k :b :v 2}]
            [:a {:k :a :v 3}]
            [:c {:k :c :v 4}]]
           (->> xs
                (rx/seq->o)
                (rx/group-by :k)
                (rx/flatmap (fn [[k vo :as me]]
                              (is (instance? clojure.lang.MapEntry me))
                              (rx/map #(vector k %) vo)))
                (b/into [])))))

  ; still looking for a simple demo of merging for the multi-arg case
  ; Here, because ys is "inline", the interleaving is removed. sigh.
  (let [xs [{:k :a :v 1} {:k :b :v 2} {:k :a :v 3} {:k :c :v 4}]
        ys [:ay :by :cy]]
    (is (= [[:a {:k :a :v 1} :ay]
            [:a {:k :a :v 3} :ay]
            [:b {:k :b :v 2} :by]
            [:c {:k :c :v 4} :cy]]
           (->> (rx/flatmap (fn [[k vo :as me] y]
                              (is (instance? clojure.lang.MapEntry me))
                              (rx/map #(vector k % y) vo))
                            (->> xs
                                 rx/seq->o
                                 (rx/group-by :k))
                            (rx/seq->o ys))
                (b/into []))))))
fluree/db
(ns json-ld.query
  (:require [clojure.core.async :as async]
            [fluree.db.flake :as flake]
            [fluree.db.json-ld.api :as fluree]
            [fluree.db.util.async :refer [<?? go-try channel?]]
            [fluree.db.query.range :as query-range]
            [fluree.db.constants :as const]
            [fluree.db.dbproto :as dbproto]
            [fluree.db.did :as did]
            [fluree.json-ld :as json-ld]
            [fluree.db.indexer.default :as indexer]
            [fluree.db.indexer.proto :as idx-proto]
            [fluree.db.util.log :as log]
            [fluree.db.index :as index]
            [criterium.core :as criterium]
            [fluree.db.query.analytical-parse :as q-parse]))

  @(fluree/query db {:select   ['?name '?last '(sum ?favNums)]
                     :where    [['?s :schema/name '?name]
                                ['?s :ex/last '?last]
                                ['?s :ex/favNums '?favNums]]
                     :group-by ['?name '?last]})
fluree/ledger
(ns fluree.db.ledger.docs.query.advanced-query
  (:require [clojure.test :refer :all]
            [fluree.db.test-helpers :as test]
            [fluree.db.ledger.docs.getting-started.basic-schema :as basic]
            [fluree.db.api :as fdb]
            [clojure.core.async :as async]
            [fluree.db.util.log :as log]))


(deftest group-by-with-limit-offset
  (testing "Group By query with limit returns first two full results"
    (let [query-all {:select "?favNums"
                     :where  [["?e" "person/favNums" "?favNums"]]
                     :groupBy "?e"}
          query-limit {:select "?favNums"
                       :where  [["?e" "person/favNums" "?favNums"]]
                       :groupBy "?e"
                       :limit 2}
          query-offset {:select "?favNums"
                        :where  [["?e" "person/favNums" "?favNums"]]
                        :groupBy "?e"
                        :offset 2
                        :limit 2}
          db  (basic/get-db test/ledger-chat)
          res-all  (async/<!! (fdb/query-async db query-all))
          res-limit (async/<!! (fdb/query-async db query-limit))
          res-offset (async/<!! (fdb/query-async db query-offset))]


(deftest group-by-with-having
  (testing "Group By query with 'having' statement defined for filter"
    (let [q-all          {:select "(sum ?favNums)"
                          :where   [["?e" "person/favNums" "?favNums"]]
                          :groupBy "?e"}
          q-having       {:select  "(sum ?favNums)"
                          :where   [["?e" "person/favNums" "?favNums"]]
                          :groupBy "?e"
                          :having  (str '(< 200 (sum ?favNums)))}
          q-having+and   {:select  "(sum ?favNums)"
                          :where   [["?e" "person/favNums" "?favNums"]]
                          :groupBy "?e"
                          :having  (str '(and (< 200 (sum ?favNums)) (> 1900 (sum ?favNums))))}
          db             (basic/get-db test/ledger-chat)
          res-all        (async/<!! (fdb/query-async db q-all))
          res-having     (async/<!! (fdb/query-async db q-having))
          res-having+and (async/<!! (fdb/query-async db q-having+and))
          ;; get a vector of all ?favNums sums
          all-sums (vals res-all)]

(deftest advanced-query-test
  (crawl-graph)
  (crawl-graph-reverse)
  (crawl-graph-reverse-add)
  (select-no-ns-preds)
  (select-with-as)
  (select-with-as-and-limit)
  (graphql-with-reverse-ref)
  (crawl-graph-two)
  ;(crawl-graph-two-with-recur)
  (aggregate-binding)
  (group-by-with-limit-offset)
  (group-by-with-having)
  (multi-query))
  ;(multi-query-with-error)
ghl3/dataframe
(ns dataframe.frame-test
  (:require [dataframe.frame :as frame :refer [index]]
            [expectations :refer [expect expect-focused more-of]]
            [dataframe.series :as series]
            [clojure.core :as core]))


(expect (more-of grouped
                 (frame/frame {:a [1 2] :b [10 20]} [0 1]) (:foo grouped)
                 (frame/frame {:a [3] :b [30]} [2]) (:bar grouped))
        (frame/group-by
          (frame/frame {:a [1 2 3] :b [10 20 30]})
          [:foo :foo :bar]))

(expect (more-of grouped
                 (frame/frame {:a [3 2] :b [30 20]} [2 1]) (:foo grouped)
                 (frame/frame {:a [1] :b [10]} [0]) (:bar grouped))
        (frame/group-by
          (frame/frame {:a [1 2 3] :b [10 20 30]})
          (series/series [:foo :foo :bar] [2 1 0])))


(expect (more-of grouped
                 (frame/frame {:a [1 1] :b [10 20]} [0 1]) (get grouped 1)
                 (frame/frame {:a [3] :b [30]} [2])        (get grouped 3))
        (frame/group-by-fn
          (frame/frame {:a [1 1 3] :b [10 20 30]}) :a))


(expect (more-of grouped
                 (frame/frame {:a [1 10] :b [10 1]} [0 2]) (get grouped 11)
                 (frame/frame {:a [1] :b [5]} [1])         (get grouped 6)
                 (frame/frame {:a [10] :b [17]} [3])       (get grouped 27))
        (frame/with-> (frame/frame {:a [1 1 10 10] :b [10 5 1 17]})
                (frame/group-by (series/add $a $b))))