If I have an array map like this:
{"red" "blue"}
How can I turn this into an array like this:
["red" "blue"]
Maps hold an unordered set of MapEntry objects, which act like vectors, so just calling first on the map will convert it to a sequence, then grab the first map entry:
(first {"red" "blue"})
; ["red" "blue"]
(vec (mapcat seq {"red" "blue"}))
; ["red" "blue"]
user> (vec (apply concat {:a 0 :b 1 :c 2 :d 3}))
[:c 2 :b 1 :d 3 :a 0]
This is similar to Thumbnail's solution, but calling seq is redundant.
Also assumed you mean vector and not array. If having the output just be linear suffices then the call to vec can be eliminated as well.
The problem with the flatten option is if there is internal structure of any sort in the map:
user> (flatten (seq {:a 0 :b 1 :c [2 3]}))
(:c 2 3 :b 1 :a 0)
user> (apply concat {:a 0 :b 1 :c [2 3]})
(:c [2 3] :b 1 :a 0)
If you want to handle empty maps as empty vectors and maps with multiple pairs as a vector of [key val key val...] then you can use reduce into [] or reduce-kv conj [].
so.core=> (reduce into [] {"red" "blue"})
["red" "blue"]
so.core=> (reduce into [] {:a 0 :b 1 :c 2 :d 3})
[:c 2 :b 1 :d 3 :a 0]
so.core=> (reduce into [] {})
[]
One and a very quick way:
(flatten (vec {"red" "blue"}))
=> ("red" "blue")
If you really want an array:
(into-array (flatten (vec {"red" "blue"})))
=> #<String[] [Ljava.lang.String;#4dc2753>
Keep in mind that in Clojure, ["red" "blue"] is a vector, not an array. And { } means map. Clojure first creates an array map but later, it promotes it to hash map when it is necessary.
Related
Is there something like pprint or clojure.pprint/pprint available in Hy? More specific, is there something that would convert something like this:
{:a {:a 0 :b 1 :c 2 :d 3 :e 4} :b {:a 0 :b 1 :c 2 :d 3 :e 4} :c {:a 0 :b 1 :c 2 :d 3 :e 4} :d {:a 0 :b 1 :c 2 :d 3 :e 4} :e {:a 0 :b 1 :c 2 :d 3 :e 4}}
In this (this is an example, doesn't need to be exactly like below):
{:e {:e 4 :d 3 :c 2 :b 1 :a 0}
:d {:e 4 :d 3 :c 2 :b 1 :a 0}
:c {:e 4 :d 3 :c 2 :b 1 :a 0}
:b {:e 4 :d 3 :c 2 :b 1 :a 0}
:a {:e 4 :d 3 :c 2 :b 1 :a 0}}
I already tried hy-repr and hydiomatic.utils/hypprint, however hy-repr didn't seem to pretty print long maps and hydiomatic does not work in recent versions of Hy.
No. Feel free to file an issue requesting it. However, our Emacs package, hy-mode, does have some auto-indent features (partly borrowed from Emacs's generic Lisp-editing code), and probably the Vim plugin does too, but that's been less actively maintained (to nobody's surprise, Lispers tend to prefer Emacs).
How could I cut off an array or an array-reference in Perl 6?
In Perl 5, I can do this:
my $d = [0 .. 9];
$#$d = 4;
In Perl 6, I get an error if I try this:
my $d = [0 .. 9];
$d.end = 4; # Cannot modify an immutable Int
This works, but it looks less beautiful than the Perl 5 way and may be expensive:
$d.=splice(0, 5);
There is a simple way:
my $d = [0..9];
$d[5..*] :delete;
That is problematic if the array is an infinite one.
$d.splice(5) also has the same problem.
Your best bet is likely to be $d = [ $d[^5] ] in the average case where you may not know anything about the array, and need a mutable Array.
If you don't need it to be mutable $d = $d[^5] which returns a List may be better.
splice is probably the best choice here, but you can also shorten to five elements using the ^N range constructor shortcut (I call this the "up until" "operator" but I am sure there is a more correct name since it is a constructor of a Range):
> my $d = [ 0 .. 9 ];
> $d.elems
> 10
> $d = [ $d[^5] ]
[0 1 2 3 4]
> $d.elems
5
> $d
[0 1 2 3 4]
"The caret is ... a prefix operator for constructing numeric ranges
starting from zero".
(From the Range documentation)
One can argue that perl6 is "perl-ish" in the sense it usually has an explicit version of some operation (using a kind of "predictable" syntax - a method, a routine, and :adverb, etc.) that is understandable if you are not familiar with the language, and then a shortcut-ish variant.
I'm not sure which approach (splice vs. the shortcut vs. using :delete as Brad Gilbert mentions) would have an advantage in speed or memory use. If you run:
perl6 --profile -e 'my $d = [ 0 .. 9 ]; $d=[ $d[^5] ]'
perl6 --profile -e 'my $d = [ 0 .. 9 ]; $d.=splice(0, 5);'
you can see a slight difference. The difference might be more significant if you compared with a real program and workload.
Another option is using the xx operator:
my $d = [0..9];
$d.pop xx 4; #-> (9 8 7 6)
say $d; #-> [0 1 2 3 4 5]
$d = [0..9];
$d.shift xx 5 #-> (0 1 2 3 4)
say $d; #-> [5 6 7 8 9)
In Clojure, I want to be able to multiply all numbers in a set and add them all to a new set to return.
=>(multiply-all #{ 1 2 3})
#{1 4 6 3 2 9}
Here's my implementation:
(defn multiply-all [num-set]
(loop [new-set num-set
cur-set num-set]
(if (= 0 (count cur-set)) new-set
(recur (into new-set (map #(* (first cur-set) %) num-set)) (rest cur-set)))))
Is there a way to do this using doseq WITHOUT using transients. Something like this:
(let [s #{ 1 2 3}]
(doseq [outer s]
(doseq [inner s]
(let [multiplied (* outer inner)]
(println (conj s multiplied))
))))
I'm interested in any suggestions for a cleaner way to do this.
---EDIT----
Here's another way using reduce:
(defn multiply-all2 [num-set]
(let [step (fn [[ result ] mult]
[(into result (map #(* mult %) num-set))])]
(first (reduce step [num-set] num-set))))
doseq is for side effects. You probably want to use for instead:
user=> (set (for [a #{1 2 3}
b #{1 2 3}]
(* a b)))
#{1 4 6 3 2 9}
(defn multiply-all [s]
(set (mapcat #(map * s (repeat %)) s)))
I've been using Matlab for quite awhile but this one has got me--I want a one-liner that will take an array and write it into the indexed entries of a cell, e.g.
>> c = cell(1,6);
>> b = [1 2 3];
>> c{[2 4 6]} = b; %This doesn't actually work
>> disp(c)
[] [1] [] [2] [] [3]
I've tried all sorts of versions of this with num2cell, deal et al. but I can't find the magic bullet. Can it be done in a single assignment?
With mat2cell -
c([2 4 6]) = mat2cell(b,1,ones(1,numel(b)));
With num2cell -
c([2 4 6]) = num2cell(b);
Output -
>> disp(c)
[] [1] [] [2] [] [3]
I'm using Clojure and I need to run a small simulation. I have a vector of length n (n is usually between 10 and 100) that holds values. On each simulation round (maybe 1000 rounds together), one of the values in the vector is updated randomly. I guess I could do this by using an Java array and calling the aset method, but this would break the functional programming/immutability idiom.
Is there a more functional way to do this, or should I just go with the Java array?
(defn run-sim [arr num-iters update-fn]
(if (zero? num-iters)
arr
(let [i (rand-int (count arr))
x (update-fn)]
(println "setting arr[" i "] to" x)
(recur (assoc arr i x) (dec num-iters) update-fn))))
user> (run-sim [1 2 3 4 5 6 7 8 9 10] 10 #(rand-int 1000))
setting arr[ 8 ] to 167
setting arr[ 4 ] to 977
setting arr[ 5 ] to 810
setting arr[ 5 ] to 165
setting arr[ 3 ] to 486
setting arr[ 1 ] to 382
setting arr[ 4 ] to 792
setting arr[ 8 ] to 478
setting arr[ 4 ] to 144
setting arr[ 7 ] to 416
[1 382 3 486 144 165 7 416 478 10]
There's no shame in using a Java array if you need it though. Especially if you need it to go fast. Limit the array-mutation to the inside of your function (clone the input array and work on that maybe) and no one will be the wiser.
Adding to Brian's answer: If you need more speed, you can also resort to transients.
(defn run-sim
[vektor num-iters update-fn]
(loop [vektor (transient vektor)
num-iters (int num-iters)]
(if (zero? num-iters)
(persistent! vektor)
(let [i (rand-int (count vektor))
x (update-fn)]
(recur (assoc! vektor i x) (dec num-iters))))))
Lets first define a function which updates a random index in a vector with a new value. Note that the original vector is not changed, instead a new vector (with the updated value) is returned:
(defn f [xs]
(let [r (java.util.Random.)
i (.nextInt r (count xs))
b (.nextBoolean r)]
(assoc xs i ((if b inc dec) (xs i)))))
This function chooses an index and then it either increases or decreases the value at that index by 1. You must of course change this function to your needs.
Then it is a simple matter to compose this function with itself as many times you want to run the simulation:
user=> ((apply comp (repeat 1000 f)) [0 0 0 0 0 0 0])
[7 -4 7 6 10 0 -6]
It's not that Clojure won't let you change values, it's just a little more cumbersome.
(def vec-ref (ref my-vector))
(dosync (set! vec-ref (assoc my-vector index value))
to look at values in the changed vector, use #vec-ref.
Could be off in details - I'm not near a REPL, unfortunately. But it should get you started.