Fork me on GitHub
#clojure-uk
<
2020-08-20
>
dharrigan06:08:03

Good MOrning!

mccraigmccraig09:08:11

hey @agile_geek, long time!

👋 3
alexlynham09:08:58

was thinking the same thing

maleghast14:08:27

Hello All...

maleghast15:08:35

I have a weird question... How would you filter a lazySeq of maps from a map of keys and values that would make up the predicates? e.g.

{:place-city "Manchester"
 :place-iso-country-code "GB"}
Would need to be run as two successive filters on lazySeq "coll":
(->> coll
(filter #(= "Manchester"  (:place-city %)))
(filter #(= "GB"  (:place-iso-country-code %))))

alexlynham15:08:15

i'd use juxt and then collect those two seqs i think

maleghast15:08:30

I thought of turning the map into a list of vector pairs and reducing over it, but it appears to cause all kinds of type exception horror and basically doesn't work. Same with extracting the keys from the map and reducing over the list of keys

alexlynham15:08:45

why not just use juxt?

maleghast15:08:53

@alex.lynham - I don't know how I would...

maleghast15:08:11

It's core library, but I've never used it.

alexlynham15:08:58

((juxt :place-city :place-iso-country-code) coll)

maleghast15:08:24

Also it's not two seqs, it's one Lazy Seq that needs to get smaller and smaller with each successive filter - the map of filter predicates could be a lot bigger

alexlynham15:08:59

are you filtering by a set?

alexlynham15:08:12

sorry i thought you wanted several split out seqs

maleghast15:08:00

no, I am taking a bunch of querystring params and turning them into a map in order to filter a LazySeq of maps based on equality predicates made from each key-value pair in the map.

mccraigmccraig15:08:11

can you give an example of the input->output mappings @maleghast? i'm struggling to understand the specification atm

alexlynham15:08:36

it sounds like you're filtering with a contains predicate over a set?

alexlynham15:08:15

ahh no i mean some

maleghast15:08:15

input -> LazySeq of Maps output -> List of Maps that conform to a single or multiple filters

maleghast15:08:48

The predicates for the filters are equality based on key/value from a simple 1d map that is created from querystring parameters

alexlynham15:08:55

(some #{:your-keys} coll)?

alexlynham15:08:13

ahh no that'll only return the first

maleghast15:08:27

keys and values, @alex.lynham I want all the maps that have a match for the value of one or more keys

maleghast15:08:42

I can take the LazySeq of maps and ->>filter it, but creating the anonymous functions to provide the predicates inside the filter forms is the bit I can't seem to wrap my head around.

maleghast15:08:01

If I knew the keys and values in advance it would be fine, but I don't

alexlynham15:08:18

i guess it's just 2 dimensional in that case

alexlynham15:08:53

my brain jumps to it's something like, make a list of paths, then iterate those on each element, presto

maleghast15:08:54

so /api/places/search?place-city=Manchester&place-iso-country-code=GB gives rise to the map above ^^ From that I want to programatically create the procession of filters, or at least the same effect as filtering the LazySeq of maps several times

maleghast15:08:30

the resulting list of maps should be places that are located in Manchester, GB

alexlynham15:08:02

yeah like i say it feels simple, grab those values, and iterate over 'em

maleghast15:08:14

Yeah, but how..?

mccraigmccraig15:08:56

so you want output equivalent to filtering the places collection first with #(= "Manchester" (:city %)) and then #(= "GB" (:iso-country-code %)) ?

maleghast15:08:42

@mccraigmccraig - Yes, but the predicates could be anything, I don't know in advance what will be on the querystring.

mccraigmccraig15:08:22

(fn make-pred [k v] (fn [r] (= v (get r k))))

maleghast15:08:27

so I am turning the querystring into a map and then trying to drive this process off that map.

alexlynham15:08:37

dammit craig

alexlynham15:08:42

how did you type that so fast

alexlynham15:08:01

i had just written the inner bit lol

maleghast15:08:31

Hold on, this is writing a function to return a function ^^ right?

mccraigmccraig15:08:53

yes, to make a filter predicate from a key-value pair

maleghast15:08:13

So I get how I would do that if I had one key / value pair, but if I have 1 or more how do I run filter on all of them one after another..?

maleghast15:08:49

Am I on the right track about reducing over the list of predicates..? That seems to throw a wobbler

mccraigmccraig15:08:10

yes, reduce the predicates onto the seq

mccraigmccraig15:08:26

something like (reduce (fn [coll' pred] (filter pred coll')) coll pred-list)

maleghast15:08:46

I think that I can make that work... Thanks! Just want to say that I realise having asked the question that I already knew that I could return a function from a function, but I would never have thought of it in a million years without your help, so thanks both. For making me explain it and for pointing out the big "return a function" blindspot in my thinking 🙂

maleghast15:08:45

@mccraigmccraig - Worked, first time - thanks SO MUCH!

maleghast15:08:08

@alex.lynham - Thanks also for engaging and helping me realise I was not explaining well