7

How do I convert a clojure map into string, almost key value pair, as shown below:

Clojure data:

(def data { :starks "Winter is coming" :Lannisters "Hear me roar" })

I want to convert the above to

"starks" "winter is coming" "Lannisters" "hear me roar"

I don't want any identifiers / delimiters between but obviously "starks" should always be followed by "winter is coming"

I tried this:

(str (keys data) (vals data))

Which outputs this:

"(:starks :Lannisters)(\"Winter is coming\" \"Hear me roar\")"

Which is not what I want at all...

  • The map data keys and values are not always the same so it needs to be generic
  • there will always be just one level, as in, the value will not contain a nested map etc..

Edit

What I'm actually trying to do:

I am trying to index a few thousand Neo4j nodes with clojure. To help me with this task, I am using Neocons Clojure neo4j library.

According to the documentation, the add-to-index accepts properties and values like so:

(nn/add-to-index (:id node) (:name idx) "username" "joe")))

which is, in my above case, going to look like

(nn/add-to-index (:id node) (:name idx) "starks" "winter is coming" "Lannisters" "Hear me roar")))

now, I have my Node, I can access the node properties with (:data node) and that gives me a clojure map.

The property differs pretty much from node to node so I'm trying to figure out how to pass that map to the library in the way that it understands..

Marius Danila's answer got me almost there.

Doing

(map name (apply concat data))

still complains of the third parameter, as it has the braces around the result.

So, how can I achieve this? Do I just have to write a whole lot of if-not blocks to construct the properties myself?

Thanks

4 Answers 4

8

This should do the trick:

(map name (apply concat data))

A map can be viewed as a sequence of key-value pairs, which in turn represented as arrays of 2 elements. We're concatenating the pairs and then we extract the name from the keywords and strings (for string this does nothing, for keywords it returns the bit without ':').

From the code you've posted, I'm guessing you would use this like so:

(apply nn/add-to-index (list* (:id node) (:name idx) (map name (apply concat data))))
Sign up to request clarification or add additional context in comments.

7 Comments

Hi, Thanks! this is almost getting me there, but I have a braces around the string.. like so: ("starks" "Winter is coming" "Lannisters" "Hear me roar") - Trying to convert to string and replacing it isn't working as expected.. how do I get rid of the braces please? I just need it as a string, for example
@LocustHorde Ok, I've updated my answer. I hope it's what you're looking for.
Hi, sorry, I may be not communicating correctly, I need the array of strings, with keys and their respective values next to each other.. I'll update the question.. Thank you very much.
Actually, on a second thought, I might be able to work with this, let me try it and get back please. thanks.
Ok, so I gave it one last shot :)
|
2

The (nn/add-to-index ...) function simply accepts only four arguments. The node, index and one key/value pair. So you have too loop through your data like.

(doseq [[k v] data]
  (nn/add-to-index (:id node) (:name idx) (name k) (clojure.string/lower-case v))))

Unlike the the str function in Clojure the add-to-index function is more limited and simply does not accept variable parameter lists.

2 Comments

Ooh, that makes so much sense now! Thank you very much, will modify my code to reflect this. Thanks again!
yes, that works perfectly, thank you! I swear I could add several properties at the same time.. but obviously I am thinking of something else. Thanks again!
2

You can use vector to have array like random access:

=> (def v (vec (map name (apply concat data))))
=> (v 0)
;"starks"
=> (v 1)
;"Winter is coming"

Comments

2

You could try the following:

=> (interleave (map name (keys data)) (vals data))

;; which returns ("starks" "Winter is coming" "Lannisters" "Hear me roar")

1 Comment

Hi, thanks, this gives the same result as Marius Danila's answer. The latest answer on this question tells me that the function does not actually take more than 4 arguments.I swear I thought I could pass any number of arguments to it! but thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.