I have this deeply nested list (list of lists) and I want to replace a single arbitrary element in the list. How can I do this ? (The built-in replace might replace many occurrences while I need to replace only one element.)
Share
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
As everyone else already said, using lists is really not a good idea if you need to do this kind of thing. Random access is what vectors are made for.
assoc-indoes this efficiently. With lists you can’t get away from recursing down into the sublists and replacing most of them with altered versions of themselves all the way back up to the top.This code will do it though, albeit inefficiently and clumsily. Borrowing from dermatthias:
Usage:
You’ll get
IndexOutOfBoundsExceptionif you give anyngreater than the length of a sublist. It’s also not tail-recursive. It’s also not idiomatic because good Clojure code shies away from using lists for everything. It’s horrible. I’d probably use mutable Java arrays before I used this. I think you get the idea.Edit
Reasons why lists are worse than vectors in this case:
You also don’t have to write
assoc-inyourself, it already exists. Look at the implementation forassoc-insometime; it’s simple and straightforward (compared to the list version) thanks to vectors giving efficient and easy random access by index, viaget.You also don’t have to quote vectors like you have to quote lists. Lists in Clojure strongly imply “I’m calling a function or macro here”.
Vectors (and maps, sets etc.) can be traversed via
seqs. You can transparently use vectors in list-like ways, so why not use vectors and have the best of both worlds?Vectors also stand out visually. Clojure code is less of a huge blob of parens than other Lisps thanks to widespread use of
[]and{}. Some people find this annoying, I find it makes things easier to read. (My editor syntax-highlights(),[]and{}differently which helps even more.)Some instances I’d use a list for data:
lazy-seq