How to use reduce and into properly - clojure

I'm learning Clojure and actually I'm doing some exercises to practice but I'm stuck in a problem:
I need to make a sum-consecutives function which sums consecutive elements in a array, resulting in a new one, as example:
[1,4,4,4,0,4,3,3,1] ; should return [1,12,0,4,6,1]
I made this function which should work just fine:
(defn sum-consecutives [a]
(reduce #(into %1 (apply + %2)) [] (partition-by identity a)))
But it throws an error:
IllegalArgumentException Don't know how to create ISeq from:
java.lang.Long clojure.lang.RT.seqFrom (RT.java:542)
Can anyone help me see what is wrong with my func? I've already search this error in web but I find no helpful solutions.

You'll likely want to use conj instead of into, as into is expecting its second argument to be a seq:
(defn sum-consecutives [a]
(reduce
#(conj %1 (apply + %2))
[]
(partition-by identity a)))
(sum-consecutives [1,4,4,4,0,4,3,3,1]) ;; [1 12 0 4 6 1]
Alternatively, if you really wanted to use into, you could wrap your call to apply + in a vector literal like so:
(defn sum-consecutives [a]
(reduce
#(into %1 [(apply + %2)])
[]
(partition-by identity a)))

Your approach is sound in starting with partition-by. But let's
walk through the steps to sum each subsequence that it produces.
(let [xs [1 4 4 4 0 4 3 3 1]]
(partition-by identity xs)) ;=> ((1) (4 4 4) (0) (4) (3 3) (1))
To get a sum, you can use reduce (though a simple apply
instead would also work
here); e.g.:
(reduce + [4 4 4]) ;=> 12
Now put it all together to reduce each subsequence from above with map:
(let [xs [1 4 4 4 0 4 3 3 1]]
(map #(reduce + %) (partition-by identity xs))) ;=> (1 12 0 4 6 1)
A few notes...
I'm using xs to represent your vector (as suggested by the
Clojure Style Guide).
The let is sometimes a convenient form for experimenting with some
data building up to eventual functions.
Commas are not needed and are usually distracting, except occasionally
with hash-maps.
So your final function based on all this could look something like:
(defn sum-consecutives [coll]
(map #(reduce + %) (partition-by identity coll)))

Related

Higher-order if-then-else in Clojure?

I often have to run my data through a function if the data fulfill certain criteria. Typically, both the function f and the criteria checker pred are parameterized to the data. For this reason, I find myself wishing for a higher-order if-then-else which knows neither f nor pred.
For example, assume I want to add 10 to all even integers in (range 5). Instead of
(map #(if (even? %) (+ % 10) %) (range 5))
I would prefer to have a helper –let's call it fork– and do this:
(map (fork even? #(+ % 10)) (range 5))
I could go ahead and implement fork as function. It would look like this:
(defn fork
([pred thenf elsef]
#(if (pred %) (thenf %) (elsef %)))
([pred thenf]
(fork pred thenf identity)))
Can this be done by elegantly combining core functions? Some nice chain of juxt / apply / some maybe?
Alternatively, do you know any Clojure library which implements the above (or similar)?
As Alan Thompson mentions, cond-> is a fairly standard way of implicitly getting the "else" part to be "return the value unchanged" these days. It doesn't really address your hope of being higher-order, though. I have another reason to dislike cond->: I think (and argued when cond-> was being invented) that it's a mistake for it to thread through each matching test, instead of just the first. It makes it impossible to use cond-> as an analogue to cond.
If you agree with me, you might try flatland.useful.fn/fix, or one of the other tools in that family, which we wrote years before cond->1.
to-fix is exactly your fork, except that it can handle multiple clauses and accepts constants as well as functions (for example, maybe you want to add 10 to other even numbers but replace 0 with 20):
(map (to-fix zero? 20, even? #(+ % 10)) xs)
It's easy to replicate the behavior of cond-> using fix, but not the other way around, which is why I argue that fix was the better design choice.
1 Apparently we're just a couple weeks away from the 10-year anniversary of the final version of fix. How time flies.
I agree that it could be very useful to have some kind of higher-order functional construct for this but I am not aware of any such construct. It is true that you could implement a higher order fork function, but its usefulness would be quite limited and can easily be achieved using if or the cond-> macro, as suggested in the other answers.
What comes to mind, however, are transducers. You could fairly easily implement a forking transducer that can be composed with other transducers to build powerful and concise sequence processing algorithms.
The implementation could look like this:
(defn forking [pred true-transducer false-transducer]
(fn [step]
(let [true-step (true-transducer step)
false-step (false-transducer step)]
(fn
([] (step))
([dst x] ((if (pred x) true-step false-step) dst x))
([dst] dst))))) ;; flushing not performed.
And this is how you would use it in your example:
(eduction (forking even?
(map #(+ 10 %))
identity)
(range 20))
;; => (10 1 12 3 14 5 16 7 18 9 20 11 22 13 24 15 26 17 28 19)
But it can also be composed with other transducers to build more complex sequence processing algorithms:
(into []
(comp (forking even?
(comp (drop 4)
(map #(+ 10 %)))
(comp (filter #(< 10 %))
(map #(vector % % %))
cat))
(partition-all 3))
(range 20))
;; => [[18 20 11] [11 11 22] [13 13 13] [24 15 15] [15 26 17] [17 17 28] [19 19 19]]
Another way to define fork (with three inputs) could be:
(defn fork [pred then else]
(comp
(partial apply apply)
(juxt (comp {true then, false else} pred) list)))
Notice that in this version the inputs and output can receive zero or more arguments. But let's take a more structured approach, defining some other useful combinators. Let's start by defining pick which corresponds to the categorical coproduct (sum) of morphisms:
(defn pick [actions]
(fn [[tag val]]
((actions tag) val)))
;alternatively
(defn pick [actions]
(comp
(partial apply apply)
(juxt (comp actions first) rest)))
E.g. (mapv (pick [inc dec]) [[0 1] [1 1]]) gives [2 0]. Using pick we can define switch which works like case:
(defn switch [test actions]
(comp
(pick actions)
(juxt test identity)))
E.g. (mapv (switch #(mod % 3) [inc dec -]) [3 4 5]) gives [4 3 -5]. Using switch we can easily define fork:
(defn fork [pred then else]
(switch pred {true then, false else}))
E.g. (mapv (fork even? inc dec) [0 1]) gives [1 0]. Finally, using fork let's also define fork* which receives zero or more predicate and action pairs and works like cond:
(defn fork* [& args]
(->> args
(partition 2)
reverse
(reduce
(fn [else [pred then]]
(fork pred then else))
identity)))
;equivalently
(defn fork* [& args]
(->> args
(partition 2)
(map (partial apply (partial partial fork)))
(apply comp)
(#(% identity))))
E.g. (mapv (fork* neg? -, even? inc) [-1 0 1]) gives [1 1 1].
Depending on the details, it is often easiest to accomplish this goal using the cond-> macro and friends:
(let [myfn (fn [val]
(cond-> val
(even? val) (+ val 10))) ]
with result
(mapv myfn (range 5)) => [10 1 14 3 18]
There is a variant in the Tupelo library that is sometimes helpful:
(mapv #(cond-it-> %
(even? it) (+ it 10))
(range 5))
that allows you to use the special symbol it as you thread the value through multiple stages.
As the examples show, you have the option to define and name the transformer function (my favorite), or use the function literal syntax #(...)

how to find whether a vector has consecutive elements in clojure

I am new to clojure
I am trying to find whether a vector in clojure has consecutive elements:
in python its simple using numpy
(np.diff(np.sort(np.array(numbers))))
But I am lost trying to find similar methods:
My strategy was to
subtract a vector with itself
make it a set and see if it contains first element as 1 and the length of set is 1
for example
(def x `(5 7 3 6 4))
Output would be (1 1 1 1)
I am confused how to work on this.
Try something like this:
(defn diff [vals]
(map - (next vals) vals))
This returns a list of differences between each pair of consecutive elements are equal. It works because next simply offsets the sequence of values by one element.
Example usage:
(diff [1 2 2 3])
=> (1 0 1)
To test whether consecutive numbers exist, you simply need to check for the presence of the value 1 in this list.
Following your idea of getting the differences, after sorting you can use partition to get all the consecutive pairs and than use map to get all the differences. (Here it seemed more natural to get the reverse of the numpy diff, so the check is that every element is -1 instead of 1.)
(defn contains-consecutive? [xs]
(let [sorted (sort xs)
differences (map #(apply - %) (partition 2 1 sorted))]
(every? #(= -1 %) differences)))
user> (contains-consecutive? [])
true
user> (contains-consecutive? [1])
true
user> (contains-consecutive? [1 3 2])
true
user> (contains-consecutive? [1 3 4])
false
user> (contains-consecutive? '(5 7 3 6 4))
true
Clojure has a built-in dedupe function so an easy (but not particularly fast) answer is to dedupe and compare equals.
(defn consecutive?
[coll]
(not= coll (dedupe coll)))
(consecutive? [1 2 2 3]) ;; true
(consecutive? [1 2 3]) ;; false
Please see this list of documentation, especially the Clojure CheatSheet. You are looking for the function partition. You can use it like this:
(ns tst.demo.core
(:use tupelo.test))
(defn pair-delta
[pair]
(let [[a b] pair]
(- b a)))
(defn consectives?
[v]
(let [pairs (partition 2 1 (sort v))
deltas (mapv pair-delta pairs)
result (= #{1} (set deltas))]
result))
(dotest
(let [pos [1 2 3 6 5 4]
neg [1 2 3 6 5 ]]
(is= true (consectives? pos))
(is= false (consectives? neg))))
The template project shows how I like to set up a project, and includes my favorite helper functions.

Good way in clojure to map function on multiple items of coll or seqence

I'm currently learning Clojure, and I'm trying to learn how to do things the best way. Today I'm looking at the basic concept of doing things on a sequence, I know the basics of map, filter and reduce. Now I want to try to do a thing to pairs of elements in a sequence, and I found two ways of doing it. The function I apply is println. The output is simply 12 34 56 7
(def xs [1 2 3 4 5 6 7])
(defn work_on_pairs [xs]
(loop [data xs]
(if (empty? data)
data
(do
(println (str (first data) (second data)))
(recur (drop 2 data))))))
(work_on_pairs xs)
I mean, I could do like this
(map println (zipmap (take-nth 2 xs) (take-nth 2 (drop 1 xs))))
;; prints [1 2] [3 4] [5 6], and we loose the last element because zip.
But it is not really nice.. My background is in Python, where I could just say zip(xs[::2], xs[1::2]) But I guess this is not the Clojure way to do it.
So I'm looking for suggestions on how to do this same thing, in the best Clojure way.
I realize I'm so new to Clojure I don't even know what this kind of operation is called.
Thanks for any input
This can be done with partition-all:
(def xs [1 2 3 4 5 6 7])
(->> xs
(partition-all 2) ; Gives ((1 2) (3 4) (5 6) (7))
(map (partial apply str)) ; or use (map #(apply str %))
(apply println))
12 34 56 7
The map line is just to join the pairs so the "()" don't end up in the output.
If you want each pair printed on its own line, change (apply println) to (run! println). Your expected output seems to disagree with your code, so that's unclear.
If you want to dip into transducers, you can do something similar to the threading (->>) form of the accepted answer, but in a single pass over the data.
Assuming
(def xs [1 2 3 4 5 6 7])
has been evaluated already,
(transduce
(comp
(partition-all 2)
(map #(apply str %)))
conj
[]
xs)
should give you the same output if you wrap it in
(apply println ...)
We supply conj (reducing fn) and [] (initial data structure) to specify how the reduce process inside transduce should build up the result.
I wouldn't use a transducer for a list that small, or a process that simple, but it's good to know what's possible!

Performant way to group elements in a collection into new collections with Clojure

I have a collection (a Java List) of tens of thousands of elements and I'm writing a Clojure function that needs to split this list into several parts based on predicates. In the end I have several Clojure collections with only elements matching the predicate associated with the collection.
The following code solves my problem but iterates over the input list 3 times. Is there a better way to do this?
(defn divide-into-groups [col]
(let [one (filter #(< % 3) col)
two (filter #(and (>= % 3) (< % 6)) col)
three (filter #(>= % 6) col)]
[one two three]))
(divide-into-groups (shuffle (range 10)))
;[(2 0 1) (4 3 5) (6 8 7 9)]
I'm really looking for a functional Clojure solution. I already know I could create three collections as vars and mutate them inside the divide-into-groups function and maybe that is the Clojure way. If so, then please say so.
(NOTE: the predicates I use above are not the ones in my production code. The data I'm working with is also not numbers. This is just a SSCCE. The answer to this question must be applicable to the general problem with arbitrary data in the collection and arbitrary predicates. And of course, performant. To be clear, the lazy lists returned by filter will all be completely iterated over and used to generate some output. So I cannot rely on lazy solutions ;-)
This is what group-by is for. The only thing you need other than your predicates is to give each of your predicate groups a "name" to dictate what group it will be in:
(defn divide-into-groups [xs]
(let [group (fn [x] (cond (>= x 6) :large
(>= 6 x 3) :medium
:else :small))]
(group-by group xs)))
user> (divide-into-groups (shuffle (range 10)))
{:small [1 2 0], :large [6 9 8 7], :medium [3 4 5]}
You could use partition-by[1].
(partition-by (fn [x] (cond (< x 3) :coll-1
(and (>= x 3) (< x 6)) :coll-2
(>= x 6) :coll-3))
(range 10))
The required function can be constructed programmatically from the sequence of predicate functions. The unique value, ie :coll-1, :coll-2 etc can be anything, even the index of the predicate in the sequence.
EDIT:
;; updated to use map-indexed and some-fn as suggested by #Andre
(defn partitions
[preds coll]
(let [party-fn (apply some-fn
(map-indexed (fn [idx pred]
#(when (pred %1) idx))
preds))]
(partition-by party-fn coll)))
;; output
(partitions [ #(< %1 3) #(<= 3 %1 5) #(>= %1 6)] (range 10))
((0 1 2) (3 4 5) (6 7 8 9))
[1] - https://clojuredocs.org/clojure.core/partition-by

How to map a function that adds 5 to its argument?

Please help me get off the ground with Clojure. I've searched and read, but all I see is how to add the number 1 using the function inc.
I'm trying to understand the very basics of map. All I want to do is to add the value 5 to each element in a collection. I've tried a number of different approaches, but nothing comes close. Here is one pathetic incomplete attempt:
(map (+ 5 ???) [0 1 2])
This must be childishly simple, but not for a non-functional programmer like me.
Thanks.
The first argument to map is the function you want to apply to each element in the input sequence. You could create a function and supply it:
(defn plus5 [x] (+ 5 x))
(map plus5 [0 1 2])
if you don't want to declare a named function you could create an anonymous one inline e.g.
(map (fn [x] (+ 5 x)) [0 1 2])
and you can shorten the function definition to:
(map #(+ 5 %) [0 1 2])
(+ 5 ???) is an expression, not a function.
(defn foo [x] (+ 5 x)) is a named function.
(fn [x] (+ 5 x)) is an anonymous function.
#(+ 5 %) is a faster way of writing an anonymous function.
These lines do what you want:
(map foo [0 1 2])
(map (fn [x] (+ 5 x)) [0 1 2])
(map #(+ 5 %) [0 1 2])
I find this site helpful sometimes, when looking at a language I've never seen before. If you search for "function," you'll find a whole section on how to define them. There are also six examples in the official Clojure docs for map. This is for Scala, but here's another answer on SO that explains map and reduce (left fold) pretty well.
Use partial application (see partial) to create a function that adds 5 to its argument:
(partial + 5)
You can try it yourself:
user> ((partial + 5) 10)
;; => 15
Now map it over your list:
user> (map (partial + 5) [0 1 2])
;; => [5 6 7]