Flipping elements in Clojure - clojure

If I input a vector and wanted to flip the elements' order, I'd write
(reverse [1 2 3])
Now, how would I generalize this idea to be able to input nested vectors and flip the order of elements? Given a matrix A the function should reverse the elements in each column.

Based on the example you gave in the comments, this is exactly what reverse does given a collection that contains collections. You want reverse.

Related

Using Filter on vectors

I am trying to use the filter function over a vector called dataset that is defined like so:
AK,0.89,0.98
AR,0.49,0.23
AN,0.21,0.78
...
And I want to get all of the values that contain a certain string, something like this:
(filter (contains "AK") dataset)
Which would return:
AK,0.89,0.98
Is it possible to do this using the filter function?
I already iterate over the vector using doseq but I'm required to use filter at some point in my code.
Thanks :)
The basic answer is yes, you can use filter to do this. Filter expects a
predicate function i.e. a function which returns true or false. The filter
function will iterate over the elements in the collection you pass in and pass
each element from that collection to the predicate. What you do inside the
predicate function is totally up to you (though you should make sure to avoid
side effects). Filter will collect all the elements where the predicate returned
true into a new lazy sequence.
Essentially, you have (long form)
(filter (fn [element]
; some test returning true/fals) col)
where col is your collection. The result will be a LAZY SEQUENCE of elements
where the predicate function returned true. It is important to understand that
things like filter and map return lazy sequences and know what that really means.
The critical bit to understand is the structure of your collection. In your
description, you stated
I am trying to use the filter function over a vector called dataset
that is defined like so:
AK,0.89,0.98 AR,0.49,0.23 AN,0.21,0.78 ...
Unfortunately, your description is a little ambiguous. If your dataset structure
is actually a vector of vectors (not simply a vector), then things are very
straight-forward. This is because it will mean that each 'element' passed to the
predicate function will be one of your 'inner' vectors. The real definition is
more accurately represented as
[
[AK,0.89,0.98]
[AR,0.49,0.23]
[AN,0.21,0.78]
...
]
what will be passed to the predicate is a vector of 3 elements. If you just want
to select all the vectors where the first element is 'AK', then the predicate
function could be as simple as
(fn [el]
(if (= "AK" (first el))
true;
false))
So the full line would be something like
(filter (fn [el]
(if (= "AK" (first el))
true
false)) [[AK 0.89 0.98] [AR 0.49 0.23] [AN 0.21 0.78]])
and that is just the start and very verbose version. There is lots you can do to
make this even shorter e.g.
(filter #(= "AK" (first %)) [..])
If on the other hand, you really do just have a single vector, then things
become a little more complicated because you would need to somehow group the
values. This could be done by using the partition function to break up your
vector into groups of 3 items before passing them to filter e.g.
(filter pred (partition 3 col))
which would group the elements in your original vector into groups of 3 and pass
each group to the predicate function. This is where the real power of map,
filter, reduce, etc come into play - you can transform the data, passing it
through a pipeline of functions, each of which somehow manipulates the data and
a final result pops out the end.
The key point is to understand what filter (and other functions like this, such
as map or reduce) will understand as an 'element' in your input
collection. Basically, this is the same as what would be returned by 'first'
called on the collection. This is what is passed to the predicate function in
fileter.
There are a lot of assumptions here. One of the main ones is that your data is
strictly ordered i.e. the value you are looking to test is always the first
element in each group. If this is not the case, then more work will need to be
done. Likewise, we assume the data is always in groups of 3. If it isn't, then other approaches will be needed.

Difference in behavior of conj on vectors and lists in Clojure

I am new to clojure, initially i am going through Clojure.org and cheatbook .
I want to know what is exact reason for different behavior of conj on list and vector.
(conj [1 2 3] 4)
[1 2 3 4]
(conj (list 3 2 1) 4)
(4 3 2 1)
when i am using it with list it add element in first location and with vector it add at last location.
The conj procedure adds new elements "at different 'places' depending on the concrete type". In particular, conj is adding new elements at the most efficient place for the given data structure.
In a single-linked list, the cheapest place to insert a new element is at the head - there's no need to traverse the list to find the insertion point, just connect the new element with the list's first element.
In a vector, the cheapest place is at the end - there's no need to shift or move the rest of the elements to make room for the new element, and if the vector was created with extra free space with actual size greater than its current length (as is the case with transient vectors and conj!, but not with persistent vectors), it's a simple matter of adding the new element at the first free position and incrementing its length by one unit.

how to model the below transformation

I have a hashmap of data with the key a string description and value an integer weight.
{:a 2 :b 3 ......}
I need to transform the hash into a vector of vectors. Each internal vector contains the map entries.
[[[:a 2][:b 3]...][......]]
each internal vector is built based upon some rules. Ex the sum of all weights should not exceed a certain value
Normally this seems to be a good case for a reduce where a hash is transformed into a vector of vectors of map entries. However I may need to iterate over the hash more than once as I may need to reshuffle the entries between the internal vectors so that all of the vectors sum up to a certain num.
Any suggestions on how the problem should me modelled?
Well, for starters, Clojure maps are already sequences of vectors. So no reduce needed:
=> (for [e {:a 1 :b 2}] e)
([:a 1] [:b 2])
Instead of thinking of it as "iterating," you should take the approach of defining a function that takes your input vectors and returns a new sequence with the adjustment. Recursively call this function until the sum you need is reached.

Fast insert into the beginning and end of a clojure seq?

In clojure lists grow from the left and vectors grow from the right, so:
user> (conj '(1 2 3) 4)
(4 1 2 3)
user> (conj [1 2 3] 4)
[1 2 3 4]
What's the most efficient method of inserting values both into the front and the back of a sequence?
You need a different data structure to support fast inserting at both start and end. See https://github.com/clojure/data.finger-tree
As I understand it, a sequence is just a generic data structure so it depends on the specific implementation you are working with.
For a data structure that supports random access (e.g. a vector), it should take constant time, O(1).
For a list, I would expect inserting at the front of the list with a cons operation to take constant time, but inserting to the back of the list will take O(n) since you have to traverse the entire structure to get to the end.
There is, of course, a lot of other data structures that can theoretically be a sequence (e.g. trees) that will have their own O(n) characteristics.

Clojure rseq in Constant Time?

I was reading in Practical Clojure (Chapter 5) that the rseq function operation executes in constant time. It seems to me that it should be a linear time operation. Can anyone shed some light on this for me?
Try this:
(class [1 2 3 4])
You'll see:
clojure.lang.PersistentVector
Now try this:
(class (rseq [1 2 3 4]))
And the sequence implementation is different:
clojure.lang.APersistentVector$RSeq
As Roman said, it is a changed interface to a sequence. All the elements are where they were you are just accessing them in a reverse order.
You can see RSeq class to see how it's implemented here: https://github.com/clojure/clojure/blob/b578c69d7480f621841ebcafdfa98e33fcb765f6/src/jvm/clojure/lang/APersistentVector.java
I don't know how it's implemented, but I would think it just returns some object that implements sequence interface and knows how to traverse the structure (vector or sorted map) in reverse order. The result sequence is lazy, so it doesn't have to traverse the whole structure immediately.
It returns the new interface in constant time like Goran Jovic said but printing it out is linear. So displaying it in the REPL is linear, but putting it in a def is constant.