How can I update an item in a vector in Clojure? - clojure

If I have a Vector:
[1 2 3 4 5 6 7 8 9]
: and I want to replace the 5 with a 0 to give:
[1 2 3 4 0 6 7 8 9]
How can I do this when I only know the index as being 4?
Something like:
(replace-in-vec [1 2 3 4 5 6 7 8 9] 4 0)

assoc works with vectors too!
Usage: (assoc map key val)
(assoc map key val & kvs)
assoc[iate]. When applied to a map,
returns a new map of the same
(hashed/sorted) type, that contains
the mapping of key(s) to val(s). When
applied to a vector, returns a new
vector that contains val at index.
Note - index must be <= (count
vector).
(assoc [1 2 3] 1 :a)
=> [1 :a 3]

You want assoc: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/assoc

Related

Multiply nested pairs of list values in Clojure

What I am ultimately trying to do is multiply two vectors together and return a vector of the same size eg:
[6 7 8 9 10] * [0 1 3 1 0] => [0 7 24 9 0]
I was attempting to do something like:
(partition 2 (interleave [6 7 8 9 10] [0 1 3 1 0])) => ((6 0) (7 1) (8 3) (9 1) (10 0))
... then multiply each nested list value and use flatten to get:
(0 7 24 9 0)
but I cant figure out how I could multiply nested list values?
Map takes multiple sequences and a function to combine each member with the corresponding member of the other sequences.
user> (map * [6 7 8 9 10] [0 1 3 1 0])
(0 7 24 9 0)
user> (mapv * [6 7 8 9 10] [0 1 3 1 0])
[0 7 24 9 0]
in this case it calls * on the first number from each list, then on the second from each list and so on, building a seq of the output. If you would prefer the output in a vector mapv is convenient.

How to convert a map into a collection without the keys

I have a map like this:
{1 [1 4 7], 2 [2 5 8], 0 [3 6 9]}
I want to write a function that returns this:
[[1 4 7] [2 5 8] [3 6 9]]
As a side note, I'm getting the map by doing this:
(group-by #(mod % 3) [1 2 3 4 5 6 7 8 9])
If anyone has a shortcut for going from a vector like this: [1 2 3 4 5 6 7 8 9] to the second one shown above, please let me know!
As to your other question: (partition 3 v) creates a matrix, and (apply map vector m) is an idiom to transpose a matrix m (how does it work? Exercise for the reader or google it). So:
> (apply map vector (partition 3 [1 2 3 4 5 6 7 8 9]))
([1 4 7] [2 5 8] [3 6 9])
There are other ways of course. For example, with destructuring:
> (let [{ a 0 b 1 c 2 } (group-by #(mod % 3) [1 2 3 4 5 6 7 8 9])] [b c a])
[[1 4 7] [2 5 8] [3 6 9]]
Does order matter? vals is takes a map, and returns a sequence of the values. But order is not defined for a map, so the order of the values sequence returned is arbitrary.
> (vals {1 [1 4 7], 2 [2 5 8], 0 [3 6 9]})
([3 6 9] [1 4 7] [2 5 8])
Sorted:
> (sort (vals {1 [1 4 7], 2 [2 5 8], 0 [3 6 9]}))
([1 4 7] [2 5 8] [3 6 9])

Clojure: 'folding' a sequence (partitioning, as it turned out)

What is the right way of turning a flat list like this:
(1 2 3 4 5 6 7 8 9)
into a sequence of vectors:
([1 2 3] [4 5 6] [7 8 9])
Sorry, I suppose this is something right out of the toolbox, but I can't think of the right keyword.
(->> '(1 2 3 4 5 6 7 8 9) (partition 3) (map vec))
Take the original list and then partition it by 3 and finally map each partition to a vector.
I think using the ->> macro makes it read nicer.
user> (def flat-seq (range 1 10))
#'user/flat-seq
user> (map vec (partition-all 3 flat-seq))
;=> ([1 2 3] [4 5 6] [7 8 9])

finding if a vector's all elements only appear once

I have a vector - [1 2 3 4]
I want to check that in the vector each element appears only once. How do I do it ? One way I can think of is to convert it into a set and then back into the vector and then compare both :) However I think there should be a simpler way ...
You can use distinct?:
(apply distinct? [1 2 3 4]) ;=> true
(apply distinct? [1 2 3 4 4]) ;=> false
You can use distinct:
(distinct [1 2 3 4 5 5]) -> [1 2 3 4 5]
For a check, you can do something like:
(= [1 2 3 4 5 5] (distinct [1 2 3 4 5 5]))

count unique values in vector in clojure

I was wondering if anyone can help me understand how can i do the below code in clojure :
int[] secondArray = new int[500];
for (int i = 0; i < firstArray.length; i++)
{
secondArray[firstArray[i]] += 1;
}
You could probably use the frequencies function:
user=> (frequencies [:foo :bar :baz :foo :foo])
{:foo 3, :bar 1, :baz 1}
Let's walk through a fairly direct translation where we treat the input vector as a sequence and then reduce it into the desired result:
First define some immutable vectors containing our starting states:
boo> (def firstVector (vec (take 30 (repeatedly #(rand-int 10)))))
#'boo/firstVector
boo> firstVector
[9 0 4 5 0 7 3 9 0 0 6 6 5 5 9 4 0 1 3 6 4 9 5 8 8 3 4 6 7 6]
boo> (def secondVector (vec (take 10 (repeat 0))))
#'boo/secondVector
boo> secondVector
[0 0 0 0 0 0 0 0 0 0]
We then want an expression that incs the appropriate element in the second array
boo> (assoc secondVector 4 (inc (secondVector 4)))
[0 0 0 0 1 0 0 0 0 0]
Then we want the result of that to be passed to the frist element in firstVector, followed by the result of that being passed to the second element in firstVector and so forth. The reduce function does this:
boo> (reduce #(assoc %1 %2 (inc (%1 %2))) secondVector firstVector)
[5 1 0 3 4 4 5 2 2 4]
in the reducer function %1 (the first argument) is the current accumulated result, and %2(the second argument) is the current value from the input sequence (firstVector).