[英]Idiomatic string rotation in Clojure
How to idiomatically rotate a string in Clojure for the Burrows-Wheeler transform ? 如何在Clojure中为Burrows-Wheeler转换惯用旋转字符串?
I came up with this, which uses (cycle "string")
, but feels a bit imperative: 我想出了这个,它使用(cycle "string")
,但感觉有点必要:
(let [s (str "^" "banana" "|")
l (count s)
c (cycle s)
m (map #(take l (drop % c)) (range l))]
(apply map str m))
=> ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
I'm not sure if this qualifies as code golf. 我不确定这是否符合代码高尔夫的要求。 Is there a cleaner way to do this? 有更清洁的方法吗?
I would do: 我会做:
(defn bwrot [s]
(let [s (str "^" s "|")]
(for [i (range (count s))]
(str (subs s i) (subs s 0 i)))))
or: 要么:
(defn bwrot [s]
(let [n (+ 2 (count s))
s (str "^" s "|^" s "|")]
(for [i (range n)]
(subs s i (+ i n)))))
The second one should allocate less (one string instead of three per iteration). 第二个应该分配更少(每个迭代一个字符串而不是三个)。
There used to be a rotations
function in clojure.contrib.seq
that might be worth a look for inspiration. 曾经有一个clojure.contrib.seq
中的rotations
功能,可能值得寻找灵感。 The source is reproduced below: 来源如下:
(defn rotations
"Returns a lazy seq of all rotations of a seq"
[x]
(if (seq x)
(map
(fn [n _]
(lazy-cat (drop n x) (take n x)))
(iterate inc 0) x)
(list nil)))
Then you could do something like: 然后你可以这样做:
(apply map str (rotations "^banana|"))
; => ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
If I was unconcerned about efficiency or number of characters I'd write something like: 如果我不关心效率或字符数,我会写一些像:
(defn rotate-string
[s]
(apply str (concat (drop 1 s) (take 1 s))))
(defn string-rotations
[s]
(->> s
(iterate rotate-string)
(take (count s))))
(rotate-string "^banana|") ; "banana|^"
(string-rotations "^banana|") ; ("^banana|" "banana|^" "anana|^b" "nana|^ba" "ana|^ban" "na|^bana" "a|^banan" "|^banana")
In particular, factoring out the single rotation into its own function. 特别是,将单个旋转分解为其自身的功能。
A stepped call to partition
works: 分步调用partition
工作:
(defn bwt[s]
(let [s' (str "^" s "|")
c (cycle s')
l (count s')]
(map last (sort (apply map str (take l (partition l 1 c)))))))
(apply str (bwt "banana"))
=> "|bnn^aaa"
Another way to accomplish rotation is to use a "double string" (ie concatenate the string to itself) and play around with substrings. 完成旋转的另一种方法是使用“双字符串”(即将字符串连接到自身)并使用子字符串。
(defn rotations [strng]
(let [indices (range (count strng))
doublestr (str strng strng)]
(map #(subs doublestr % (+ % (count strng))) indices)))
(rotations "^banana|")
;;(^banana| banana|^ anana|^b nana|^ba ana|^ban na|^bana a|^banan |^banana)
Rotations of "foo": 旋转“foo”:
n
of "foo" = 3 “foo”的长度n
= 3 n
substrings of "foofoo" that start with indices
0, 1, 2 and have the same length n
旋转是“foofoo”的所有n
个子串,以indices
0,1,2开始并具有相同的长度n
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.