I have a vector like this:
[1 2 "b" 4 5 6 "c" 8 9 10]
I want to add letter "a" between every element, so that the end result looks like this:
[1 "a" 2 "a" "b" "a" 4 "a" 5 "a" 6 "a" "c" "a" 9 "a" 10]
What is the best way to do this in Clojure?
Note that the letter "a" should never be the first or last element in the vector, it should only appear between other elements.
user> (interpose "a" input)
(1 "a" 2 "a" "b" "a" 4 "a" 5 "a" 6 "a" "c" "a" 8 "a" 9 "a" 10)
Or if the output has to be a vector, then
user> (vec (interpose "a" input))
[1 "a" 2 "a" "b" "a" 4 "a" 5 "a" 6 "a" "c" "a" 8 "a" 9 "a" 10]
Here is the documentation for interpose: https://clojuredocs.org/clojure.core/interpose
Related
I am trying to understand the implementation of rotating a sequence to which the answer i find in git hub is below
(fn [n coll]
(take (count coll) (drop (mod n (count coll)) (cycle coll))))
Could you please explain what is exacty happening here
(take 6 (drop 1 (cycle ["a" "b" "c"])))
("b" "c" "a" "b" "c" "a")
How is this being produced
From the documentation of cycle:
Returns a lazy (infinite!) sequence of repetitions of the items in coll.
So in your example:
(cycle ["a" "b" "c"])
;; => ["a" "b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c" ...]
(toward infinity and beyond)
To cut down an infinite sequence, you have to use take which takes the first n element of a sequence. So:
(take 6 (cycle ["a" "b" "c"]))
;; => ["a" "b" "c" "a" "b" "c"]
In your example, just before calling take, you use drop which left out the first n element of a sequence. So:
(drop 1 (cycle ["a" "b" "c"]))
;; => ["b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c" ...]
(take 6 (drop 1 (cycle ["a" "b" "c"])))
;; => ["b" "c" "a" "b" "c" "a"]
You can learn more about lazy sequences from this chapter of "Clojure from the Brave and True".
Suppose I have a list of lists I want to filter. The list is such that, in each element, the first two strings are the contents
I want to keep, the third number is the number of times it should appear in the filtered list, and the
last element is the value of the list determining what particular combination appears.
The idea is to keep only the n most valuable items of each, where n is the third element of each list inside, and the value is
determined by the last entry, but also, if there are less combinations than the third item, keep as many as possible.
Thus, in the example below, I would like to have only the first "a", "b" combination, keep the first two "a" "c" ones,
and retain the last, (even though there is no further "a" "d" combinations in it):
I have been trying to use several combinations of filter and thought about ways to retain list elements,
without success for this particular problem.
to setup
let temp-example []
set temp-example [["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 4] ["a" "c" 2 2]
["a" "c" 2 1] ["a" "d" 4 1]]
end
Desired output is the following list:
[["a" "b" 1 5]["a" "c" 2 4]["a" "c" 2 2] ["a" "d" 4 1]]
I'm sure one of the heavyweights around here will chime in soon with a one-or-two line solution, but for now I think this does what you're after. With these reporters:
to-report multifilter [ list_ ]
; Get the content pairs
let content-pairs remove-duplicates map [ i -> sublist i 0 2 ] list_
; Reorganize list into sublists for each content pair
let by-content-pairs map [ i -> filter [ j -> sublist j 0 2 = i ] list_ ] content-pairs
; Sort the sublists
let sorted-by-value map [ i -> sort-with 3 i ] by-content-pairs
; Keep only first n items of each sublist,
report reduce sentence map [ i -> keep-n 2 i ] sorted-by-value
end
to-report sort-with [ ind lst ]
; Sort the sublists by one of their indexed values
report sort-by [ [ a b ] -> ( item ind a ) > ( item ind b ) ] lst
end
to-report keep-n [ ind lst ]
; Keep only as many values as are passed by ind, or the length
; of the list, whichever value is smaller
let n item ind first lst
if n > length lst [
set n length lst
]
report sublist lst 0 n
end
Call multifilter on a list with the format you've shown and you should get your desired output:
to filter-multi
let temp-example [
["a" "b" 1 5] ["a" "b" 1 3] ["a" "c" 2 1]
["a" "c" 2 4] ["a" "c" 2 2] ["a" "d" 4 1]
]
print multifilter temp-example
end
Output:
[[a b 1 5] [a c 2 4] [a c 2 2] [a d 4 1]]
Another example:
to filter-multi
let temp-example [
["a" "b" 1 31] ["a" "b" 1 15] ["a" "b" 1 -53] ["a" "b" 1 10] ["a" "b" 1 3000]
["a" "c" 2 1] ["a" "c" 2 4] ["a" "c" 2 2] ["a" "c" 2 -10] ["a" "c" 2 14] ["a" "c" 2 40]
["a" "d" 4 1] ["a" "d" 4 12]
]
print multifilter temp-example
end
Output:
[[a b 1 3000] [a c 2 40] [a c 2 14] [a d 4 12] [a d 4 1]]
I think this more or less answers it as well:
to-report frequency [an-item a-list]
report length (filter [ i -> i = an-item] a-list)
end
; Reporter to keep the n most valuable combinations
to-report take [n xs]
report sublist xs 0 min list n (length xs)
end
to go
set temp-1[]
set temp-2[]
set temp-3[]
set temp-4[]
foreach temp-example[[i] ->
set temp-1 lput (list item 0 i item 1 i) temp-1
set temp-2 lput item 2 i temp-2]
foreach temp-1[[j] ->
set temp-3 lput frequency j temp-1 temp-3
]
;First: obtain all existing combinations between the two letters:
foreach (range 0 (length temp-example)) [[j]->
ifelse item j temp-2 <= item j temp-3 [set temp-4 lput take (item j temp-2)
filter [i -> (list item 0 i item 1 i) = item j temp-1] temp-example temp-4];
[set temp-4 lput item j temp-example temp-4]; caso contrario, colocar so ate aos
item 2 j:
]
show remove-duplicates temp-4
end
I want a function that will populate the contents of this map:
{:1 "first" :2 "second" :3 "third" :4 "fourth" ... :100 "one-hundredth" ...}
So I can do something similar to
(println "This is the " (:3 {... :3 "third" ...}) " item in the sequence")
> This is the third item in the sequence
Is there an existing Clojure library that does this?
My question is: Is there a Clojure function for ordinal indicators?
(If there is a better way to describe this kind function - please let me know)
user=> (require '[clojure.pprint :as pprint])
nil
user=> (map #(pprint/cl-format nil "~:R" %) [1 2 3 4 100])
("first" "second" "third" "fourth" "one hundredth")
note that :1 is not 1, and : is not a syntax for map keys
user=> (pprint/pprint (into {} (map (fn [n] [n (pprint/cl-format nil "~:R" n)]) (range 20))))
{0 "zeroth",
7 "seventh",
1 "first",
4 "fourth",
15 "fifteenth",
13 "thirteenth",
6 "sixth",
17 "seventeenth",
3 "third",
12 "twelfth",
2 "second",
19 "nineteenth",
11 "eleventh",
9 "ninth",
5 "fifth",
14 "fourteenth",
16 "sixteenth",
10 "tenth",
18 "eighteenth",
8 "eighth"}
nil
I'm new to Clojure.
I'm developing a tic tac toe game
I'm trying to make a function that "formats" the board, which is a map with the number of the position as key and the keywords :x :o and :e for values (:e stands for empty).
I want to insert a newline character every 3 in the list of the name of the keywords.
For example "x" "x" "x" "e" "e" "e" "e" "e" "e" should be converted to "x" "x" "x" "\n" "e" "e" "e" "\n" "e" "e" "e" then I would concatenate those strings so I can print it.
(defn- newline-every
[n list]
(if (empty? list)
[]
(let [[fst snd] (split-at n list)]
(concat
(conj fst "\n")
(newline-every n snd)))))
It's Clojure so there are surely many ways to do this in one line. Here's one attempt:
(flatten (interpose "\n" (partition n list))))
As user amalloy commented, there's never an excuse to use flatten, so here's a better way:
(apply concat (interpose ["\n"] (partition n list))))
Which gives, starting from the sequence of strings (which all contain one character) you gave:
... > (newline-every 3 ["x" "x" "x" "e" "e" "e" "e" "e" "e"])
("x" "x" "x" "\n" "e" "e" "e" "\n" "e" "e" "e")
You can then transform that into a string:
... > (apply str (newline-every 3 ["x" "x" "x" "e" "e" "e" "e" "e" "e"]))
"xxx\neee\neee"
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