str makes a string of its enclosed map - dictionary

When I map inside str, I get a stringification of clojure.lang.LazySeq.
user=> (str (map inc (range 3)))
"clojure.lang.LazySeq#7861"
I've found and tried many answers - apply, doall, doseq, different mappings, mapping custom functions that use doall and other things, trying different repls, etc. - but can't seem to get map to eval before being stringified.
Update: This should also work in more general case uses of str:
user=> (str "pre string " (map inc (range 3)) " post string")
Desired output:
user=> "pre string 123 post string"

You need something like this?
(apply str (map inc (range 3)))
=> "123"
Show us your desired output to make sure that we are on the same page.
Still, I don't know what is your desired output.
(str "pre string " (apply str (map inc (range 3))) " post string")
=> "pre string 123 post string"

use seq
(str (seq (map inc (range 3))))
"(1 2 3)"

Related

In Dr. Racket, how would I convert a list of strings to a list of list of strings

In Dr. Racket, how would I convert a list containing strings (each string is separated by a space) to a list containing a list of the separated strings. If you can't understand the question too well, here is an example:
Given a list like:
(list "abc def" "ghj elm" "ref tio" "pol mnb")
I want to produce:
(list (list "abc" "def") (list "ghj" "elm") (list "ref" "tio") (list "pol" "mnb"))
I wrote up a code for it but I quickly got stuck. Here is my code so far:
(define (a los)
(cond
[(empty? los) empty]
[(char-whitespace? (first los)) (substring (list->string los) 1)]
[else (a (rest los))]))
For example:
(a (string->list "abc def"))
Produces "def".
I was hoping to first separate the strings in the list based on the whitespace and then I would piece them together to form new lists. However, I don't know how to do this.
Any tips/hints on how to do this are much appreciated.
There's a built-in procedure called string-split that does just what you need, it's as simple as this:
(define (split-list los)
(map string-split los))
It works as expected:
(split-list '("abc def" "ghj elm" "ref tio" "pol mnb"))
=> '(("abc" "def") ("ghj" "elm") ("ref" "tio") ("pol" "mnb"))

Clojure: Vector is not immutable

I'm running into a problem where immutability suddenly doesn't hold for my vectors. I was wondering if there was a way to create fresh, immutable vector copies of a given set.
Clojuredocs suggested "aclone" but that is giving me an error stating that there's no such method.
(defn stripSame [word wordList]
(def setVec (into #{} wordList))
(def wordSet word)
(def wordVec (into #{} [wordSet]))
(def diffSet (set/difference setVec wordVec))
(def diffVec (into [] diffSet))
diffVec)
(defn findInsOuts [word passList]
(def wordList (stripSame word passList))
(println word wordList)
(def endLetter (subs word (dec (count word))))
(def startLetter (subs word 0 1))
(println startLetter endLetter)
(def outs (filter (partial starts endLetter) wordList))
(def ins (filter (partial ends startLetter) wordList))
;(println ins outs)
(def indexes [ (count ins) (count outs)])
indexes)
(defn findAll [passList]
(def wordList (into [] passList) ))
(println wordList)
(loop [n 0 indexList []]
(println "In here" (get wordList n) wordList)
(if (< n (count wordList))
(do
(def testList wordList)
(def indexes (findInsOuts (get wordList n) testList))
(println (get wordList n) indexes)
(recur (inc n) (conj indexList [(get wordList n) indexes]))))))
passList is a list of words like so (lol at good) which is then cast into a vector.
So basically findAll calls findInsOuts which goes through every word in the list and sees how many other words start with its last letter but which first removes the search word from the vector before performing some function to prevent duplicates. The problem is that somehow this vector is actually mutable, so the copy of the vector in findAll also has that value permanently stripped.
When I try to create a new vector and then act on that vector the same thing still happens, which implies that they're aliased/sharing the same memory location.
How can I create a fresh vector for use that is actually immutable?
Any help is appreciated
I'm afraid your code is riddled with misunderstandings. For a start, don't use def within defn. Use let instead. This turns your first function into ...
(defn stripSame [word wordList]
(let [setVec (into #{} wordList)
wordSet word
wordVec (into #{} [wordSet])
diffSet (clojure.set/difference setVec wordVec)
diffVec (into [] diffSet)]
diffVec))
For example,
=> (stripSame 2 [1 2 :buckle-my-shoe])
[1 :buckle-my-shoe]
The function can be simplified to ...
(defn stripSame [word wordList]
(vec (disj (set wordList) word)))
... or, using a threading macro, to ...
(defn stripSame [word wordList]
(-> wordList set (disj word) vec))
I don't think the function does what you think it does, because it doesn't always preserve the order of elements in the vector.
If I were you, I'd work my way through some of the community tutorials on this page. There are several good books referred to there too. Once you get to grips with the idioms of the language, you'll find the sort of thing you are trying to do here much clearer and easier.

Is there a way to make map over a Clojure vector of maps use a destructing bind?

I'm using this code:
(println
(mapcat
(fn [my-map]
(str (:key my-map) (:value my-map) "\n"))
[{:key 1 :value 2}{:key 3 :value 4}]))
I think there is a way to make it shorter using a destructing bind.
My question is: Is there a way to make map over a Clojure vector of maps use a destructing bind?
You can bind the values directly in the function argument list:
(println
(mapcat
(fn [{k :key, v :value}]
(str k v "\n"))
[{:key 1 :value 2} {:key 3 :value 4}]))

Getting index and size of collection when using the map function

I have this scenario. I use the map function in Clojure to apply a custom function on a collection. This function takes a while to execute and my collection is pretty large. I would like to be able to print something like this during each call of my function:
"Doing some stuff... (index/total)"
where index is the current element in the collection and total is the size. Is there a way to do this easily in clojure? I could send the size as a parameter to my collection. Also, I could, probably, use some kind of counter, but I was wondering if there was something built-in...
Thanks
user=> (map-indexed (fn [idx itm] [idx itm]) "foobar")
([0 \f] [1 \o] [2 \o] [3 \b] [4 \a] [5 \r])
map-indexed
(defn sebi [collection]
(map-indexed #(println (format "Doing some stuff with %s (%d/%d)"
%2 (inc %1) (count collection)))
collection))
(sebi ["Mary" "had" "a" "little" "lamb"])
You may pass lazy counter and sequence of size into map with collection.
(defn sebi [collection]
(map #(println (format "Doing some staff with %s (%d/%d)" %1 (inc %2) %3))
collection
(range)
(repeat (count collection)))
(sebi ["Mary" "had" "a" "little" "lamb"])
The other answers will work, but you might wan to modify them so the total is only calculated once (i.e. use a "(let [cnt (count collection)]...). Or you could look at clj-progress which is a full featured progress reporting lib.
(defn map-reporting
[msg f coll]
(let [c (count coll)]
(doall (map-indexed (fn [e i]
(println msg (str "[" (inc i) "/" c "]"))
(f e)) coll))))
user> (map-reporting "Doing some stuff" inc (range 5))
Doing some stuff [1/5]
Doing some stuff [2/5]
Doing some stuff [3/5]
Doing some stuff [4/5]
Doing some stuff [5/5]
(1 2 3 4 5)

What's the canonical way to join strings in a list?

I want to convert ("USERID=XYZ" "USERPWD=123") to "USERID=XYZ&USERPWD=123". I tried
(apply #'concatenate 'string '("USERID=XYZ" "USERPWD=123"))
which will return ""USERID=XYZUSERPWD=123".
But i do not know how to insert '&'? The following function works but seems a bit complicated.
(defun join (list &optional (delim "&"))
(with-output-to-string (s)
(when list
(format s "~A" (first list))
(dolist (element (rest list))
(format s "~A~A" delim element)))))
Use FORMAT.
~{ and ~} denote iteration, ~A denotes aesthetic printing, and ~^ (aka Tilde Circumflex in the docs) denotes printing the , only when something follows it.
* (format nil "~{~A~^, ~}" '( 1 2 3 4 ))
"1, 2, 3, 4"
*
This solution allows us to use FORMAT to produce a string and to have a variable delimiter. The aim is not to cons a new format string for each call of this function. A good Common Lisp compiler also may want to compile a given fixed format string - which is defeated when the format string is constructed at runtime. See the macro formatter.
(defun %d (stream &rest args)
"internal function, writing the dynamic value of the variable
DELIM to the output STREAM. To be called from inside JOIN."
(declare (ignore args)
(special delim))
(princ delim stream))
(defun join (list delim)
"creates a string, with the elements of list printed and each
element separated by DELIM"
(declare (special delim))
(format nil "~{~a~^~/%d/~:*~}" list))
Explanation:
"~{ iteration start
~a print element
~^ exit iteration if no more elements
~/%d/ call function %d with one element
~:* move one element backwards
~}" end of iteration command
%d is just an 'internal' function, which should not be called outside join. As a marker for that, it has the % prefix.
~/foo/ is a way to call a function foo from a format string.
The variables delim are declared special, so that there can be a value for the delimiter transferred into the %d function. Since we can't make Lisp call the %d function from FORMAT with a delimiter argument, we need to get it from somewhere else - here from a dynamic binding introduced by the join function.
The only purpose of the function %d is to write a delimiter - it ignores the arguments passed by format - it only uses the stream argument.
Melpa hosts the package s ("The long lost Emacs string manipulation library"), which provides many simple string utilities, including a string joiner:
(require 's)
(s-join ", " (list "a" "b" "c"))
"a, b, c"
For what it's worth, very thinly under the hood, it's using a couple lisp functions from fns.c, namely mapconcat and identity:
(mapconcat 'identity (list "a" "b" "c") ", ")
"a, b, c"
A bit late to the party, but reduce works fine:
(reduce (lambda (acc x)
(if (zerop (length acc))
x
(concatenate 'string acc "&" x)))
(list "name=slappy" "friends=none" "eats=dogpoo")
:initial-value "")
Assuming a list of strings and a single character delimiter, the following should work efficiently for frequent invocation on short lists:
(defun join (list &optional (delimiter #\&))
(with-output-to-string (stream)
(join-to-stream stream list delimiter)))
(defun join-to-stream (stream list &optional (delimiter #\&))
(destructuring-bind (&optional first &rest rest) list
(when first
(write-string first stream)
(when rest
(write-char delimiter stream)
(join-to-stream stream rest delimiter)))))
With the newish and simple str library:
(ql:quickload "str")
(str:join "&" '("USERID=XYZ" "USERPWD=123"))
It uses format like explained in the other answers:
(defun join (separator strings)
" "
(let ((separator (replace-all "~" "~~" separator)))
(format nil
(concatenate 'string "~{~a~^" separator "~}")
strings)))
(author of it, to make simple things like this simple).

Resources