-1

I have a map of the form

{[3.0 4.0][2.0 7.0][7.0 3.0][4.0 6.0][1.0 4.0][5.0 6.0][4.0 9.0][5.0 11.0][4.0 16.0]}

I want to group the second key in specific ranges like

((1-5)(6-10)(11-15)..)

The result should be

{{[3.0 4.0][7.0 3.0][1.0 4.0]}
{[2.0 7.0][4.0 6.0][5.0 6.0][4.0 9.0]}
{[5.0 11.0][4.0 16.0]}}

I have implemented using peek but have failed. How can I achieve this result?

esote
  • 831
  • 12
  • 25
joey
  • 259
  • 1
  • 13
  • I'm a bit confused as to how you're creating this map. What are the keys in the map? I thought a map had to have an even number of elements, but you're showing a map with an odd number of elements. ??? – Bob Jarvis - Слава Україні Sep 27 '16 at 03:34
  • @BobJarvis http://stackoverflow.com/questions/39712460/how-to-map-different-values-from-2-sets-in-clojure-based-on-unique-value/39714081?noredirect=1#comment66726590_39714081 – joey Sep 27 '16 at 03:35

1 Answers1

0

You are confusing the result of your previous question. The output of that question (and input to this one) is a set like #{...}, not a map like {...}. Each element of the set is a length-2 vector like [3 4].

The most straightforward solution is to filter each search range like so:

(ns clj.core
  (:require [tupelo.core :as t] 
            [datascript.core :as d]
            [clojure.set :as set] ))
(t/refer-tupelo)

(def data
  #{ [3.0 4.0] [2.0 7.0] [7.0 3.0] [4.0 6.0] [1.0 4.0] [5.0 6.0] [4.0 9.0] [5.0 11.0]  [4.0 16.0] } )

(println "1-5:" (filter #(<= 1 (second %) 5) data))

;=> 1-5: ([3.0 4.0] [1.0 4.0] [7.0 3.0])

or we could write a loop:

(newline)
(doseq [idx (range 5)]
  (let [upper (* (inc idx) 5)
        lower (- upper 4) ]
    (print (format "[%d..%d] => " lower upper))
    (println (filter #(<= 1 (second %) 5) data))))

[1..5]   => ([3.0 4.0] [1.0 4.0] [7.0 3.0])
[6..10]  => ([4.0 9.0] [2.0 7.0] [4.0 6.0] [5.0 6.0])
[11..15] => ([5.0 11.0])
[16..20] => ([4.0 16.0])
[21..25] => ()

Note that I fixed the data so it is a set, not a map.

You could also use group-by:

(def result4 (into (sorted-map) 
                   (group-by  #(-> % second dec (quot 5))  data)))
(newline)
(pretty result4)

{0.0 [[3.0 4.0] [1.0 4.0] [7.0 3.0]],
 1.0 [[4.0 9.0] [2.0 7.0] [4.0 6.0] [5.0 6.0]],
 2.0 [[5.0 11.0]],
 3.0 [[4.0 16.0]]}

and you can pull out the values like

(newline)
(pp/pprint (vals result4))

([[3.0 4.0] [1.0 4.0] [7.0 3.0]]
 [[4.0 9.0] [2.0 7.0] [4.0 6.0] [5.0 6.0]]
 [[5.0 11.0]]
 [[4.0 16.0]])
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • What if the result have same values. Like, (def data #{ [3.0 4.0] [3.0 4.0][3.0 4.0][2.0 7.0] [2.0 7.0] [7.0 3.0] [4.0 6.0] [1.0 4.0] [5.0 6.0] [4.0 9.0] [5.0 11.0] [4.0 16.0] } ) – joey Sep 30 '16 at 13:27
  • A set (defined using `#{...}` syntax) cannot have repeat values. Do you mean something like a vector of vectors: `[ [3 4] [3 4] [3 4] [2 7]...]` ??? – Alan Thompson Sep 30 '16 at 13:47
  • yes..I actually have the result as the vector of vectors at first – joey Sep 30 '16 at 16:25
  • The function `group-by` will work equally well with a vec of vecs instead of a set of vecs. Please try it and report back with the results. – Alan Thompson Sep 30 '16 at 17:31