HiveBrain v1.2.0
Get Started
← Back to all entries
debugMinor

Partitioning strings into substrings of fixed length

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
substringsintolengthfixedstringspartitioning

Problem

I've got a Clojure function here that's meant to parse a string of form:


"DDXXXYYY"

where DD is meant to be discarded, and XXX and YYY are string representations of integers.

(defn split-id [tileid]
  (map #(Integer/parseInt %)
       (map (partial apply str)
            (partition 3 (drop 2 tileid)))))


Or, written with the threading macro:

(defn split-id [tileid]
  (map #(Integer/parseInt %)
       (map (partial apply str)
            (->> tileid (drop 2) (partition 3)))))


Does anyone have any recommendations for a simple way to do this? It feels like clojure.contrib.string should have a partition function that takes a string and an integer.

I think I've come up with a fairly good block of code for the above function, which I had to extend a bit. I'd love comments and suggestions on the final block.

(defn parse-ints
  "Converts all strings in the supplied collection to their integer
  representation."
  [coll]
  (map #(Integer/parseInt %) coll))

(def res-map
  ^{:doc "Map between the second digit in a MODIS TileID
metadata value and the corresponding resolution."}
  {:1 "1000"
   :2 "500"
   :4 "250"})

(defn tileid->res
  "Returns a string representation of the resolution referenced by the
supplied MODIS TileID."
  [tileid]
  (res-map (keyword (subs tileid 1 2))))

(defn tileid->xy
  "Extracts integer representations of the MODIS X and Y coordinates
referenced by the supplied MODIS TileID."
  [tileid]
  (parse-ints
   (map (partial apply str)
        (partition 3 (subs tileid 2)))))

(defn split-id
  "Returns a sequence containing the resolution, X and Y
  coordinates (on the MODIS grid) referenced by the supplied MODIS
  TileID."
  [tileid]
  (flatten
   ((juxt tileid->res
          tileid->xy) tileid)))

Solution

Alternative solution is to keep it really simple:

(defn extract-int [s start end]
  (Integer/parseInt (subs s start end)))

(defn split-id [s]
  (list
    (extract-int s 2 5)
    (extract-int s 5 8)))


I believe that hardcoding two calls to extract-int is a simpler and more elegant way to meet the requirement than a solution which involves a map. Sure it's nice to use abstraction with higher-order functions, but YAGNI principle applies.

Code Snippets

(defn extract-int [s start end]
  (Integer/parseInt (subs s start end)))

(defn split-id [s]
  (list
    (extract-int s 2 5)
    (extract-int s 5 8)))

Context

StackExchange Code Review Q#631, answer score: 6

Revisions (0)

No revisions yet.