0

I'm trying to split a string into n chunks of variable sizes.

As input I have a seq of the sizes of the different chunks:

(10 6 12)

And a string:

"firstchunksecondthirdandlast"

I would like to split the string using the sizes as so:

("firstchunk" "second" "thirdandlast")

As a newbie I still have a hard time wrapping my head around the most idiomatic way to do this.

2 Answers 2

2

Here is two ways to do this:

One version uses reduce which you can use very often if you want to carry some kind of state (here: The index where you're currently at). The reduce would need a second fn call applied to it to have the result in your form.

;; Simply take second as a result:
(let [s "firstchunksecondthirdandlast"]
  (reduce
    (fn [[s xs] len]
      [(subs s len)
       (conj xs (subs s 0 len))])
    [s []]
    [10 6 12]))

The other version first builds up the indices of start-end and then uses destructing to get them out of the sequence:

(let [s "firstchunksecondthirdandlast"]
  (mapv
    (fn [[start end]]
      (subs s start end))
    ;; Build up the start-end indices:
    (partition 2 1 (reductions + (cons 0 [10 6 12])))))

Note that neither of these are robust and throw ugly errors if the string it too short. So you should be much more defensive and use some asserts.

Sign up to request clarification or add additional context in comments.

1 Comment

thank you very much for these two solutions! I actually feel dumb, it is very different from what I'm used to do in pure Java
0

Here is my go at the problem (still a beginner with the language), it uses an anonymous function and recursion until the chunks list is empty. I have found this pattern useful when wanting to accumulate results until a condition is met.

str-orig chunks-orig [] sets the initial arguments for the anonymous function: the full string, full list of chunks and an empty vec to collect results into.

(defn split-chunks [str-orig chunks-orig]
  ((fn [str chunks result]
    (if-let [len (first chunks)] (recur
                                  (subs str len)
                                  (rest chunks)
                                  (conj result (subs str 0 len)))
      result))
   str-orig chunks-orig []))

(split-chunks "firstchunksecondthirdandlast" '(10 6 12))
; ["firstchunk" "second" "thirdandlast"]

Comments

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.