Sled
Sled

Reputation: 18959

How to turn a sequence into a sequence of tuples?

I need to read through a string (which is a sequence) 3 characters at a time. I know of take-while and of take 3 and since take returns nil when there is no more input it seems like the perfect predicate for take-while but I cannot figure out how to wrap the string sequence so that it returns string of the next 3 characters at a time. If this was an object oriented language I'd wrap the sequence's read call or something, but with Clojure I have no idea how to proceed further.

Upvotes: 1

Views: 583

Answers (2)

Thumbnail
Thumbnail

Reputation: 13473

You can do this without boxing every character:

(re-seq #"..." "Some words to split")

;("Som" "e w" "ord" "s t" "o s" "pli")

If, as your comment on @turingcomplete's answer indicates, you want every other triple,

(take-nth 2 (re-seq #"..." "Some words to split"))

;("Som" "ord" "o s")

Upvotes: 2

turingcomplete
turingcomplete

Reputation: 2188

You can use partition or partition-all

(partition 3 "abcdef")

user=> ((\a \b \c) (\d \e \f))

The docs for both are

clojure.core/partition
([n coll] [n step coll] [n step pad coll])
  Returns a lazy sequence of lists of n items each, at offsets step
  apart. If step is not supplied, defaults to n, i.e. the partitions
  do not overlap. If a pad collection is supplied, use its elements as
  necessary to complete last partition upto n items. In case there are
  not enough padding elements, return a partition with less than n items.
nil


clojure.core/partition-all
([n coll] [n step coll])
  Returns a lazy sequence of lists like partition, but may include
  partitions with fewer than n items at the end.
nil

If your string is not guaranteed to be of length that is multiple of three, then you should probably use partition-all. The last partition will contain less than 3 elements though. If you want to use partition instead, then to avoid having characters from the string chopped off, you should use step=3, and a padding collection to fill in the holes in the last partition.

To turn every tuple to a string, you can use apply str on every tuple. So you'd want to use map here.

(map (partial apply str) (partition-all 3 "abcdef"))

user=> ("abc" "def")

Upvotes: 3

Related Questions